{"id":69,"date":"2026-06-02T19:13:12","date_gmt":"2026-06-02T11:13:12","guid":{"rendered":"https:\/\/jerrykhoo.com\/?p=69"},"modified":"2026-06-02T21:52:45","modified_gmt":"2026-06-02T13:52:45","slug":"siyuan-deployment-guide-docker-compose","status":"publish","type":"post","link":"https:\/\/jerrykhoo.com\/index.php\/2026\/06\/02\/siyuan-deployment-guide-docker-compose\/","title":{"rendered":"SiYuan Deployment Guide Docker Compose"},"content":{"rendered":"\n<h2 id=\"overview\" class=\"wp-block-heading\">Overview<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\"><strong>SiYuan<\/strong> (\u601d\u6e90\u7b14\u8bb0) is a privacy-first, self-hosted, fully open-source personal knowledge management system with block-level referencing and Markdown WYSIWYG editing. This guide walks through deploying it on a Linux server using Docker Compose.<\/p>\n\n\n\n<h2 id=\"architecture\" class=\"wp-block-heading\">Architecture<\/h2>\n\n\n\n<ul class=\"wp-block-list\">\n<li><strong>SiYuan<\/strong> \u2014 The knowledge management application (listens on port 6806)<\/li>\n\n\n\n<li><strong>Workspace Volume<\/strong> \u2014 Persistent data storage (mounted from host)<\/li>\n<\/ul>\n\n\n\n<p class=\"wp-block-paragraph\">SiYuan is a single-container deployment with no external database or cache dependencies \u2014 all data is stored as files in the workspace directory, making it exceptionally simple to deploy and back up.<\/p>\n\n\n\n<h2 id=\"prerequisites\" class=\"wp-block-heading\">Prerequisites<\/h2>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Assumes that you have a Linux server with Docker (24+) and Docker Compose v2+ installed<\/li>\n\n\n\n<li>Port 6806 open in your firewall (or use a reverse proxy for domain-based access)<\/li>\n\n\n\n<li>SSH access to the server<\/li>\n<\/ul>\n\n\n\n<h2 id=\"step-1-prepare-the-server\" class=\"wp-block-heading\">Step 1: Prepare the Server<\/h2>\n\n\n\n<pre class=\"wp-block-code\"><code class=\"\" data-line=\"\"># SSH into your server\nssh root@your-server-ip\n\n# Create the deployment directory\nmkdir -p \/home\/siyuan\/workspace\ncd \/home\/siyuan<\/code><\/pre>\n\n\n\n<h2 id=\"step-2-create-docker-compose-yml\" class=\"wp-block-heading\">Step 2: Create docker-compose.yml<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Create <code class=\"\" data-line=\"\">\/home\/siyuan\/docker-compose.yml<\/code>:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code class=\"\" data-line=\"\">version: &quot;3.9&quot;\nservices:\n  main:\n    image: b3log\/siyuan\n    command: &#091;&quot;--workspace=\/siyuan\/workspace\/&quot;, &quot;--accessAuthCode=${AuthCode}&quot;]\n    ports:\n    - 6806:6806\n    volumes:\n    - \/home\/siyuan\/workspace:\/siyuan\/workspace\n    restart: unless-stopped\n    environment:\n    - TZ=${TZ}\n    - PUID=${PUID}\n    - PGID=${PGID}<\/code><\/pre>\n\n\n\n<h3 id=\"configuration-parameters-explained\" class=\"wp-block-heading\">The .env file should look like the following<\/h3>\n\n\n\n<pre class=\"wp-block-code\"><code class=\"\" data-line=\"\">AuthCode=ReplacewithYourPassword\nTZ=Asia\/Singapore\nPUID=1000\nPGID=1000<\/code><\/pre>\n\n\n\n<figure class=\"wp-block-table\"><table class=\"has-fixed-layout\"><tbody><tr><th>Parameter<\/th><th>Description<\/th><\/tr><tr><td><code class=\"\" data-line=\"\">--workspace<\/code><\/td><td>Path inside the container where data is stored. Must match the volume mount.<\/td><\/tr><tr><td><code class=\"\" data-line=\"\">--accessAuthCode<\/code><\/td><td>Access authorization code \u2014 <strong>always change this!<\/strong> Without it, anyone can access your data.<\/td><\/tr><tr><td><code class=\"\" data-line=\"\">PUID \/ PGID<\/code><\/td><td>User and group IDs for file permissions. Match these to a user on your host system to avoid permission issues when accessing mounted files.<\/td><\/tr><tr><td><code class=\"\" data-line=\"\">TZ<\/code><\/td><td>Time zone for log timestamps. See <a href=\"https:\/\/en.wikipedia.org\/wiki\/List_of_tz_database_time_zones\">tz database<\/a> for valid values.<\/td><\/tr><\/tbody><\/table><\/figure>\n\n\n\n<h3 class=\"wp-block-heading\"><\/h3>\n\n\n\n<h2 id=\"step-3-set-ownership-optional\" class=\"wp-block-heading\">Step 3: Set Ownership (Optional)<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Ensure the workspace directory is owned by the user matching your PUID\/PGID:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code class=\"\" data-line=\"\">chown -R 1000:1000 \/home\/siyuan\/workspace<\/code><\/pre>\n\n\n\n<h2 id=\"step-4-deploy\" class=\"wp-block-heading\">Step 4: Deploy<\/h2>\n\n\n\n<pre class=\"wp-block-code\"><code class=\"\" data-line=\"\">cd \/home\/siyuan\n\n# Start SiYuan\ndocker compose up -d\n\n# Check container status\ndocker compose ps\n\n# View logs to confirm startup\ndocker compose logs siyuan<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">You should see log output ending with:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code class=\"\" data-line=\"\">I 2026\/06\/02 10:14:24 serve.go:231: kernel &#091;pid=1] http server &#091;0.0.0.0:6806] is booting\nI 2026\/06\/02 10:14:24 working.go:216: kernel booted<\/code><\/pre>\n\n\n\n<h2 id=\"step-5-verify-deployment\" class=\"wp-block-heading\">Step 5: Verify Deployment<\/h2>\n\n\n\n<pre class=\"wp-block-code\"><code class=\"\" data-line=\"\"># Check if the container is running\ndocker ps --filter name=siyuan --format &quot;{{.ID}} {{.Status}}&quot;\n\n# Test locally on the server\ncurl -s -o \/dev\/null -w &quot;HTTP %{http_code}&quot; http:\/\/localhost:6806\/\n\n# Check the login page (should return HTML)\ncurl -s -A &quot;Mozilla\/5.0&quot; -L http:\/\/localhost:6806\/ | head -20<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Expected: <code class=\"\" data-line=\"\">HTTP 302<\/code> (redirects to <code class=\"\" data-line=\"\">\/check-auth<\/code>) or <code class=\"\" data-line=\"\">HTTP 200<\/code> with HTML content showing the login page.<\/p>\n\n\n\n<h2 id=\"step-6-access-the-web-interface\" class=\"wp-block-heading\">Step 6: Access the Web Interface<\/h2>\n\n\n\n<ol class=\"wp-block-list\">\n<li>Open your browser to <code class=\"\" data-line=\"\">http:\/\/your-server-ip:6806<\/code><\/li>\n\n\n\n<li>You will be redirected to the <strong>Access Authorization<\/strong> login page<\/li>\n\n\n\n<li>Enter the <strong>accessAuthCode<\/strong> you configured (e.g., <code class=\"\" data-line=\"\">YourStrongAuthCodeHere!<\/code>)<\/li>\n\n\n\n<li>Once authenticated, you can start creating notes, notebooks, and organizing your knowledge<\/li>\n<\/ol>\n\n\n\n<h2 id=\"known-limitations-docker-deployment\" class=\"wp-block-heading\">Known Limitations (Docker deployment)<\/h2>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Does not support desktop and mobile application connections \u2014 only use via browser<\/li>\n\n\n\n<li>Export to PDF, HTML, and Word formats is not supported in Docker mode<\/li>\n\n\n\n<li>Importing Markdown files is not supported<\/li>\n\n\n\n<li>If you need these features, use the desktop application instead<\/li>\n<\/ul>\n\n\n\n<h2 id=\"production-hardening-checklist\" class=\"wp-block-heading\">Production Hardening Checklist<\/h2>\n\n\n\n<ul class=\"wp-block-list\">\n<li>[ ] Use a strong, unique <strong>accessAuthCode<\/strong> (not a dictionary word)<\/li>\n\n\n\n<li>[ ] Set up Nginx (or another reverse proxy) with HTTPS (Let&#8217;s Encrypt via Certbot)<\/li>\n\n\n\n<li>[ ] Configure WebSocket reverse proxy for <code class=\"\" data-line=\"\">\/ws<\/code> path when using Nginx<\/li>\n\n\n\n<li>[ ] Do NOT use URL rewriting for redirection \u2014 it may break authentication<\/li>\n\n\n\n<li>[ ] Set up regular backups of the workspace directory (<code class=\"\" data-line=\"\">\/home\/siyuan\/workspace<\/code>)<\/li>\n\n\n\n<li>[ ] Keep the Docker image updated: <code class=\"\" data-line=\"\">docker compose pull &amp;&amp; docker compose up -d<\/code><\/li>\n\n\n\n<li>[ ] Monitor logs: <code class=\"\" data-line=\"\">docker compose logs --tail=50 -f<\/code><\/li>\n\n\n\n<li>[ ] Consider using a non-root user for PUID\/PGID (1000:1000 is the default)<\/li>\n\n\n\n<li>Upgrading<\/li>\n\n\n\n<li><code class=\"\" data-line=\"\">cd \/home\/siyuan&lt;br&gt;docker compose pull&lt;br&gt;docker compose up -d<\/code><\/li>\n\n\n\n<li>SiYuan data is stored entirely in the workspace directory, so upgrades are safe and non-destructive.<\/li>\n\n\n\n<li>Test Deployment Reference<\/li>\n\n\n\n<li>This guide was verified against SiYuan <strong>v3.6.5<\/strong> on a DigitalOcean server running Ubuntu 24.04 with Docker 29.5.2 and Docker Compose v5.1.4.<\/li>\n\n\n\n<li>Troubleshooting<\/li>\n\n\n\n<li>Container keeps restarting<\/li>\n\n\n\n<li>Check the logs: <code class=\"\" data-line=\"\">docker logs siyuan<\/code>. If you see errors about <code class=\"\" data-line=\"\">\/home\/siyuan\/<\/code> not found, ensure you are using the default PUID=1000\/PGID=1000 (the container expects these to create the siyuan user&#8217;s home directory).<\/li>\n\n\n\n<li>Permission issues with mounted volumes<\/li>\n\n\n\n<li>Ensure the workspace directory on your host has the same ownership as your PUID\/PGID values:<\/li>\n\n\n\n<li><code class=\"\" data-line=\"\">chown -R 1000:1000 \/home\/siyuan\/workspace<\/code><\/li>\n\n\n\n<li>Cannot access from browser<\/li>\n\n\n\n<li>Check your firewall rules:<\/li>\n\n\n\n<li><code class=\"\" data-line=\"\"># Check if port 6806 is open&lt;br&gt;ufw status&lt;br&gt;# If ufw is enabled, allow the port&lt;br&gt;ufw allow 6806&lt;br&gt;&lt;br&gt;# Or check cloud firewall \/ security group settings on your hosting provider<\/code><\/li>\n\n\n\n<li>Resources\n<ul class=\"wp-block-list\">\n<li><a href=\"https:\/\/github.com\/siyuan-note\/siyuan\">GitHub Repository<\/a><\/li>\n\n\n\n<li><a href=\"https:\/\/hub.docker.com\/r\/b3log\/siyuan\">Docker Hub Image<\/a><\/li>\n\n\n\n<li><a href=\"https:\/\/github.com\/siyuan-note\/siyuan\/blob\/master\/README.md\">Official Documentation<\/a><\/li>\n<\/ul>\n<\/li>\n<\/ul>\n","protected":false},"excerpt":{"rendered":"<p>Overview SiYuan (\u601d\u6e90\u7b14\u8bb0) is a privacy-first, self-hosted, fully open-source personal knowledge management system with block-level referencing and Markdown WYSIWYG editing. This guide walks through deploying it on a Linux server using Docker Compose. Architecture SiYuan is a single-container deployment with no external database or cache dependencies \u2014 all data is stored as files in the [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"closed","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_gspb_post_css":"","iawp_total_views":1,"footnotes":""},"categories":[1],"tags":[10,9,8,11,7],"class_list":["post-69","post","type-post","status-publish","format-standard","hentry","category-uncategorized","tag-deployment-guide","tag-devops","tag-docker","tag-self-hosted","tag-siyuan"],"_links":{"self":[{"href":"https:\/\/jerrykhoo.com\/index.php\/wp-json\/wp\/v2\/posts\/69","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/jerrykhoo.com\/index.php\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/jerrykhoo.com\/index.php\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/jerrykhoo.com\/index.php\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/jerrykhoo.com\/index.php\/wp-json\/wp\/v2\/comments?post=69"}],"version-history":[{"count":2,"href":"https:\/\/jerrykhoo.com\/index.php\/wp-json\/wp\/v2\/posts\/69\/revisions"}],"predecessor-version":[{"id":71,"href":"https:\/\/jerrykhoo.com\/index.php\/wp-json\/wp\/v2\/posts\/69\/revisions\/71"}],"wp:attachment":[{"href":"https:\/\/jerrykhoo.com\/index.php\/wp-json\/wp\/v2\/media?parent=69"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/jerrykhoo.com\/index.php\/wp-json\/wp\/v2\/categories?post=69"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/jerrykhoo.com\/index.php\/wp-json\/wp\/v2\/tags?post=69"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}