Skip to content

Deploy on NAS (Synology, TrueNAS, QNAP)

Difficulty: Intermediate | Time: 30-45 minutes | Method: Docker/Container Station

Deploy OpenCodeHub on your Network Attached Storage (NAS) device. This is perfect for small teams, personal use, or as a private Git server at home. Works on Synology DSM, TrueNAS SCALE, QNAP QTS, and any NAS supporting Docker.


NAS TypeMinimum Requirements
SynologyDSM 7.0+, 4GB RAM (8GB recommended), x86_64 or ARM64
TrueNAS SCALE8GB RAM, 2 CPU cores, 40GB free space
QNAPQTS 5.0+, 4GB RAM, Container Station installed
GenericDocker/Podman support, 4GB RAM, 2 CPU cores
  • A domain with DDNS configured (e.g., git.yourddns.net) OR local network access only
  • Port forwarding on your router (if accessing externally):
    • 80 → NAS:80
    • 443 → NAS:443
    • 2222 → NAS:2222 (for SSH Git, optional)

  1. Open Package Center
  2. Search for Container Manager (DSM 7.2+) or Docker (older DSM)
  3. Click Install
  1. Open Control PanelShared FolderCreate

  2. Create these folders:

    • opencodehub/repos — Git repositories
    • opencodehub/storage — File uploads
    • opencodehub/ssh — SSH host keys
    • opencodehub/cache — Application cache
    • opencodehub/postgres — PostgreSQL data
    • opencodehub/redis — Redis data
  3. Set permissions:

    • Right-click each folder → EditPermissions
    • Grant Read/Write to your admin user and the Docker system group
  1. Open Container ManagerImageAddAdd from URL

  2. Image name: postgres

  3. Tag: 16-alpine

  4. Click Add

  5. Go to ContainerCreate

  6. Select postgres:16-alpine

  7. Configuration:

    • Container name: opencodehub-postgres
    • Enable auto-restart: Yes
    • Network: Use the same bridge network as other containers
    • Environment variables:
      POSTGRES_USER=opencodehub
      POSTGRES_PASSWORD=<generate-strong-password>
      POSTGRES_DB=opencodehub
    • Volume settings:
      /volume1/opencodehub/postgres → /var/lib/postgresql/data
    • Port settings:
      Local port: 5432 → Container port: 5432
  8. Click Done

Terminal window
ssh admin@your-synology-ip
sudo -i
docker run -d \
--name opencodehub-postgres \
--restart unless-stopped \
-e POSTGRES_USER=opencodehub \
-e POSTGRES_PASSWORD=YOUR_PASSWORD \
-e POSTGRES_DB=opencodehub \
-v /volume1/opencodehub/postgres:/var/lib/postgresql/data \
-p 5432:5432 \
postgres:16-alpine

Using Container Manager:

  1. Pull redis:7-alpine
  2. Create container:
    • Name: opencodehub-redis
    • Environment:
      REDIS_PASSWORD=<strong-password>
    • Command: redis-server --appendonly yes --requirepass YOUR_PASSWORD
    • Volume:
      /volume1/opencodehub/redis → /data
    • Port: 63796379

Or via SSH:

Terminal window
docker run -d \
--name opencodehub-redis \
--restart unless-stopped \
-v /volume1/opencodehub/redis:/data \
-p 6379:6379 \
redis:7-alpine \
redis-server --appendonly yes --requirepass YOUR_PASSWORD

If using the published Docker image:

Terminal window
docker run -d \
--name opencodehub \
--restart unless-stopped \
--link opencodehub-postgres:postgres \
--link opencodehub-redis:redis \
-p 4321:4321 \
-p 2222:2222 \
-e NODE_ENV=production \
-e DATABASE_URL=postgresql://opencodehub:POSTGRES_PASS@host.docker.internal:5432/opencodehub \
-e REDIS_URL=redis://:REDIS_PASS@host.docker.internal:6379 \
-e JWT_SECRET=$(openssl rand -hex 32) \
-e SESSION_SECRET=$(openssl rand -hex 32) \
-e INTERNAL_HOOK_SECRET=$(openssl rand -hex 32) \
-e CRON_SECRET=$(openssl rand -hex 32) \
-e RUNNER_SECRET=$(openssl rand -hex 32) \
-e WORKFLOW_SECRET_ENCRYPTION_KEY=$(openssl rand -hex 32) \
-e SITE_URL=https://git.yourddns.net \
-e STORAGE_TYPE=local \
-e STORAGE_PATH=/data/storage \
-e REPOS_PATH=/data/repos \
-e SSH_HOST_KEY_PATH=/data/ssh/host_key \
-v /volume1/opencodehub/repos:/data/repos \
-v /volume1/opencodehub/storage:/data/storage \
-v /volume1/opencodehub/ssh:/data/ssh \
-v /volume1/opencodehub/cache:/data/cache \
swadhinbiswas/opencodehub:latest

Note: On Synology, host.docker.internal may not work. Use your NAS IP address instead (e.g., 192.168.1.100).

  1. In Container Manager → Project (Docker Compose):
version: '3.8'
services:
app:
build:
context: /volume1/docker/OpenCodeHub
dockerfile: Dockerfile
container_name: opencodehub
restart: unless-stopped
ports:
- "4321:4321"
- "2222:2222"
environment:
- NODE_ENV=production
- DATABASE_URL=postgresql://opencodehub:YOUR_PASS@postgres:5432/opencodehub
- REDIS_URL=redis://:YOUR_PASS@redis:6379
- JWT_SECRET=YOUR_SECRET
- SESSION_SECRET=YOUR_SECRET
- INTERNAL_HOOK_SECRET=YOUR_SECRET
- CRON_SECRET=YOUR_SECRET
- RUNNER_SECRET=YOUR_SECRET
- WORKFLOW_SECRET_ENCRYPTION_KEY=YOUR_SECRET
- SITE_URL=https://git.yourddns.net
- STORAGE_TYPE=local
- STORAGE_PATH=/data/storage
- REPOS_PATH=/data/repos
- SSH_HOST_KEY_PATH=/data/ssh/host_key
volumes:
- /volume1/opencodehub/repos:/data/repos
- /volume1/opencodehub/storage:/data/storage
- /volume1/opencodehub/ssh:/data/ssh
- /volume1/opencodehub/cache:/data/cache
depends_on:
- postgres
- redis
networks:
- och-net
postgres:
image: postgres:16-alpine
container_name: opencodehub-postgres
restart: unless-stopped
environment:
- POSTGRES_USER=opencodehub
- POSTGRES_PASSWORD=YOUR_PASS
- POSTGRES_DB=opencodehub
volumes:
- /volume1/opencodehub/postgres:/var/lib/postgresql/data
networks:
- och-net
redis:
image: redis:7-alpine
container_name: opencodehub-redis
restart: unless-stopped
command: redis-server --appendonly yes --requirepass YOUR_PASS
volumes:
- /volume1/opencodehub/redis:/data
networks:
- och-net
networks:
och-net:
driver: bridge
  1. Save this as docker-compose.yml in /volume1/docker/OpenCodeHub/
  2. Clone the repo to that folder first:
    Terminal window
    cd /volume1/docker
    git clone https://github.com/swadhinbiswas/OpencodeHub.git
  3. In Container Manager → ProjectCreate
  4. Select the path /volume1/docker/OpenCodeHub
  5. Click Create

Step 1.6: Configure Reverse Proxy (Synology)

Section titled “Step 1.6: Configure Reverse Proxy (Synology)”
  1. Control PanelLogin PortalAdvancedReverse Proxy
  2. Click Create
  3. General:
    • Source:
      • Protocol: HTTPS
      • Hostname: git.yourddns.net
      • Port: 443
    • Destination:
      • Protocol: HTTP
      • Hostname: localhost
      • Port: 4321
  4. Custom HeaderCreateWebSocket
    • Header name: Upgrade
    • Value: $http_upgrade
    • Header name: Connection
    • Value: upgrade
  5. Click Save

Step 1.7: SSL Certificate (Let’s Encrypt)

Section titled “Step 1.7: SSL Certificate (Let’s Encrypt)”
  1. Control PanelSecurityCertificate

  2. Click AddAdd a new certificate

  3. Select Get a certificate from Let’s Encrypt

  4. Domain name: git.yourddns.net

  5. Email: your-email@example.com

  6. Click Apply

  7. After issuance, go to Configure and assign the certificate to:

    • git.yourddns.net:443 (your reverse proxy)

TrueNAS SCALE has native Kubernetes support with Helm charts, but Docker is easier via Apps (Docker Compose).

  1. Go to StoragePools → Your pool → Add Dataset
  2. Create a parent dataset: opencodehub
  3. Under it, create:
    • repos
    • storage
    • ssh
    • cache
    • postgres
    • redis

Step 2.2: Deploy via Custom App (Docker Compose)

Section titled “Step 2.2: Deploy via Custom App (Docker Compose)”
  1. Go to AppsDiscover AppsCustom App
  2. Enable Advanced Mode
  3. Enter this Docker Compose:
version: '3.8'
services:
app:
image: swadhinbiswas/opencodehub:latest
container_name: opencodehub
restart: unless-stopped
ports:
- "4321:4321"
- "2222:2222"
environment:
- NODE_ENV=production
- DATABASE_URL=postgresql://opencodehub:YOUR_PASS@postgres:5432/opencodehub
- REDIS_URL=redis://:YOUR_PASS@redis:6379
- JWT_SECRET=YOUR_SECRET
- SESSION_SECRET=YOUR_SECRET
- INTERNAL_HOOK_SECRET=YOUR_SECRET
- CRON_SECRET=YOUR_SECRET
- RUNNER_SECRET=YOUR_SECRET
- WORKFLOW_SECRET_ENCRYPTION_KEY=YOUR_SECRET
- SITE_URL=https://git.yourdomain.com
- STORAGE_TYPE=local
- STORAGE_PATH=/data/storage
- REPOS_PATH=/data/repos
- SSH_HOST_KEY_PATH=/data/ssh/host_key
volumes:
- /mnt/YOURPOOL/opencodehub/repos:/data/repos
- /mnt/YOURPOOL/opencodehub/storage:/data/storage
- /mnt/YOURPOOL/opencodehub/ssh:/data/ssh
- /mnt/YOURPOOL/opencodehub/cache:/data/cache
depends_on:
- postgres
- redis
networks:
- och-net
postgres:
image: postgres:16-alpine
container_name: opencodehub-postgres
restart: unless-stopped
environment:
- POSTGRES_USER=opencodehub
- POSTGRES_PASSWORD=YOUR_PASS
- POSTGRES_DB=opencodehub
volumes:
- /mnt/YOURPOOL/opencodehub/postgres:/var/lib/postgresql/data
networks:
- och-net
redis:
image: redis:7-alpine
container_name: opencodehub-redis
restart: unless-stopped
command: redis-server --appendonly yes --requirepass YOUR_PASS
volumes:
- /mnt/YOURPOOL/opencodehub/redis:/data
networks:
- och-net
networks:
och-net:
driver: bridge

Replace YOURPOOL with your actual pool name and YOUR_PASS/YOUR_SECRET with your values.

  1. Click Save
  2. TrueNAS will deploy all containers
  1. SystemGeneralGUI SSL Certificate
  2. Or use AppsCertificates for app-specific SSL
  3. For external access, use TrueNAS’s built-in ACME (Let’s Encrypt) or upload your own certificate
Section titled “Step 2.4: Reverse Proxy with Nginx Proxy Manager (Recommended)”

Install Nginx Proxy Manager from the TrueNAS Apps catalog:

  1. AppsDiscover Apps → Search “Nginx Proxy Manager”
  2. Install with default settings
  3. Access Nginx Proxy Manager at your-nas-ip:81
  4. Add Proxy Host:
    • Domain Names: git.yourdomain.com
    • Forward Hostname/IP: opencodehub
    • Forward Port: 4321
    • Enable Block Common Exploits
    • SSL: Request a new SSL certificate from Let’s Encrypt
    • Enable Force SSL and HTTP/2 Support

  1. Open App Center
  2. Search for Container Station
  3. Click Install
  1. Open File Station
  2. Create folder: opencodehub
  3. Inside it create: repos, storage, ssh, cache, postgres, redis
  1. Container Station → NetworksCreate
  2. Name: opencodehub-network
  3. Driver: Bridge
  1. CreateSearch Docker Hubpostgres:16-alpine
  2. Click Install
  3. Configuration:
    • Name: opencodehub-postgres
    • Network: opencodehub-network
    • Environment:
      POSTGRES_USER=opencodehub
      POSTGRES_PASSWORD=<password>
      POSTGRES_DB=opencodehub
    • Shared Folders:
      /share/Container/opencodehub/postgres → /var/lib/postgresql/data
    • Port: 5432
  1. Search and install redis:7-alpine
  2. Name: opencodehub-redis
  3. Network: opencodehub-network
  4. Command: redis-server --appendonly yes --requirepass YOUR_PASS
  5. Shared Folders:
    /share/Container/opencodehub/redis → /data
  1. Search and install swadhinbiswas/opencodehub:latest
  2. Name: opencodehub
  3. Network: opencodehub-network
  4. Environment variables (same as Synology example)
  5. Shared Folders:
    /share/Container/opencodehub/repos → /data/repos
    /share/Container/opencodehub/storage → /data/storage
    /share/Container/opencodehub/ssh → /data/ssh
    /share/Container/opencodehub/cache → /data/cache
  6. Ports: 4321, 2222
  1. Control PanelSystemReverse Proxy
  2. Click Create
  3. Rule:
    • Name: OpenCodeHub
    • Source Protocol: HTTPS
    • Source URL: git.yourdomain.com
    • Port: 443
    • Destination Protocol: HTTP
    • Destination URL: localhost
    • Port: 4321
  4. Enable HSTS
  1. Control PanelSecurityCertificate & Private Key
  2. Click Replace Certificate
  3. Choose Get from Let’s Encrypt
  4. Enter your domain and email
  5. Click Apply

If your NAS supports Docker (via Portainer, Podman, or CLI) and you have SSH access, the absolute easiest way to deploy is using the 1-click install script:

Terminal window
# Connect to your NAS via SSH, then run:
curl -sSL https://raw.githubusercontent.com/swadhinbiswas/OpencodeHub/main/install.sh | bash

If you prefer to deploy manually via Portainer or docker-compose.yml:

Terminal window
# Create unified data directory
mkdir -p ~/opencodehub-data
# Create docker-compose.yml
cat > ~/opencodehub/docker-compose.yml << 'EOF'
version: '3.8'
services:
app:
image: swadhinbiswas/opencodehub:latest
container_name: opencodehub
restart: unless-stopped
ports:
- "4321:4321"
- "2222:2222"
environment:
- NODE_ENV=production
- DATABASE_URL=postgresql://opencodehub:YOUR_PASS@postgres:5432/opencodehub
- REDIS_URL=redis://:YOUR_PASS@redis:6379
- JWT_SECRET=YOUR_SECRET
- SESSION_SECRET=YOUR_SECRET
- INTERNAL_HOOK_SECRET=YOUR_SECRET
- CRON_SECRET=YOUR_SECRET
- RUNNER_SECRET=YOUR_SECRET
- WORKFLOW_SECRET_ENCRYPTION_KEY=YOUR_SECRET
- SITE_URL=https://git.yourdomain.com
- DATA_DIR=/data
volumes:
- ~/opencodehub-data:/data
depends_on:
- postgres
- redis
networks:
- och-net
postgres:
image: postgres:16-alpine
container_name: opencodehub-postgres
restart: unless-stopped
environment:
- POSTGRES_USER=opencodehub
- POSTGRES_PASSWORD=YOUR_PASS
- POSTGRES_DB=opencodehub
volumes:
- ~/opencodehub-data/postgres:/var/lib/postgresql/data
networks:
- och-net
redis:
image: redis:7-alpine
container_name: opencodehub-redis
restart: unless-stopped
command: redis-server --appendonly yes --requirepass YOUR_PASS
volumes:
- ~/opencodehub-data/redis:/data
networks:
- och-net
networks:
och-net:
driver: bridge
EOF
# Deploy
cd ~/opencodehub
docker-compose up -d

For external access, forward these ports on your router:

External PortInternal IPInternal PortPurpose
80Your NAS IP80HTTP (for Let’s Encrypt/redirect)
443Your NAS IP443HTTPS (OpenCodeHub web)
2222Your NAS IP2222SSH Git (optional)

Security Note: If using a reverse proxy, you only need to forward 80 and 443. Port 4321 should NOT be exposed externally.


If you don’t have a static IP:

  1. Control PanelExternal AccessDDNS
  2. Click Add
  3. Service Provider: Synology, No-IP, DuckDNS, etc.
  4. Enter hostname: git.yourddns.net
  5. Click Test ConnectionOK
  1. NetworkGlobal ConfigurationNameservers
  2. Use Cloudflare or your DNS provider’s API for dynamic updates
  3. Or install a DDNS client as a custom app
  1. Control PanelNetwork & File ServicesDDNS
  2. Click Add
  3. Select provider and configure

Most routers (UniFi, ASUS, TP-Link) have built-in DDNS. Configure it to update git.yourddns.net automatically.


Terminal window
# Synology/QNAP/Generic
ssh admin@your-nas-ip
docker exec -it opencodehub bun run scripts/seed-admin.ts
# TrueNAS
kubectl exec -it deployment/opencodehub -- bun run scripts/seed-admin.ts

Enter username, email, and password.


  1. Visit https://git.yourddns.net (or your domain)
  2. Log in with admin credentials
  3. Create your first organization
  4. Test Git over HTTPS:
    Terminal window
    git clone https://git.yourddns.net/admin/test-repo.git

Terminal window
cd ~/opencodehub # or /volume1/docker/OpenCodeHub, etc.
docker-compose pull
docker-compose up -d
  1. Hyper BackupCreateLocal/Remote
  2. Select opencodehub shared folder
  3. Schedule: Daily at 2 AM
  4. Retention: Keep last 7 versions
# Backup script
#!/bin/bash
DATE=$(date +%Y%m%d_%H%M%S)
BACKUP_DIR="/path/to/backups"
# Database
docker exec opencodehub-postgres pg_dump -U opencodehub opencodehub | gzip > $BACKUP_DIR/och-db-$DATE.sql.gz
# Files
tar czf $BACKUP_DIR/och-files-$DATE.tar.gz /path/to/opencodehub/repos /path/to/opencodehub/storage
# Keep only last 7 days
find $BACKUP_DIR -name "och-*" -mtime +7 -delete
NASMonitoring Tool
SynologyResource Monitor widget
TrueNASReporting → CPU/Memory/Disk
QNAPResource Monitor in Dashboard

OpenCodeHub on NAS typically uses:

  • RAM: 1-2GB idle, 2-4GB under load
  • CPU: 10-30% during normal use
  • Disk: Grows with repos and uploads

ProblemSolution
Container won’t startCheck logs: docker logs opencodehub. Often a database connection issue.
”host.docker.internal” not foundUse your NAS’s LAN IP (e.g., 192.168.1.100) instead of host.docker.internal.
Permission denied on volumesEnsure the Docker user has read/write access to the shared folders. On Synology, set permissions for the Docker group.
Slow performanceNAS devices often have slow CPUs. Ensure you have at least 4GB RAM. Consider using SSD for the postgres volume.
SSL certificate errorsEnsure your domain resolves correctly. Check DDNS is updating your IP.
Git SSH not connectingPort 2222 must be forwarded on router. Some ISPs block port 22/2222. Try a different high port (e.g., 8022).
Database corruption after power lossPostgreSQL with default settings can corrupt on unclean shutdown. Use a UPS. For extra safety, add fsync=on to PostgreSQL config.
Out of memorySynology/QNAP with 2GB RAM will struggle. Close unused packages. Add a swap file if needed.

  • Enable Snapshot Replication for instant recovery
  • Use SSO Client if you want to integrate with existing domain auth
  • Consider Virtual Machine Manager if you need more isolation
  • Use Apps instead of VMs for better resource efficiency
  • Enable Automatic container updates in TrueNAS settings
  • Consider TrueCharts catalog for additional apps
  • Use QuTS hero (ZFS) for better data integrity
  • Enable snapshots for the opencodehub dataset
  • QVPN can secure remote access without exposing ports