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.
Prerequisites
Section titled “Prerequisites”| NAS Type | Minimum Requirements |
|---|---|
| Synology | DSM 7.0+, 4GB RAM (8GB recommended), x86_64 or ARM64 |
| TrueNAS SCALE | 8GB RAM, 2 CPU cores, 40GB free space |
| QNAP | QTS 5.0+, 4GB RAM, Container Station installed |
| Generic | Docker/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:80443→ NAS:4432222→ NAS:2222 (for SSH Git, optional)
Part 1: Synology DSM Deployment
Section titled “Part 1: Synology DSM Deployment”Step 1.1: Install Container Manager
Section titled “Step 1.1: Install Container Manager”- Open Package Center
- Search for Container Manager (DSM 7.2+) or Docker (older DSM)
- Click Install
Step 1.2: Create Shared Folders
Section titled “Step 1.2: Create Shared Folders”-
Open Control Panel → Shared Folder → Create
-
Create these folders:
opencodehub/repos— Git repositoriesopencodehub/storage— File uploadsopencodehub/ssh— SSH host keysopencodehub/cache— Application cacheopencodehub/postgres— PostgreSQL dataopencodehub/redis— Redis data
-
Set permissions:
- Right-click each folder → Edit → Permissions
- Grant Read/Write to your admin user and the
Dockersystem group
Step 1.3: Set Up PostgreSQL
Section titled “Step 1.3: Set Up PostgreSQL”Using Container Manager GUI:
Section titled “Using Container Manager GUI:”-
Open Container Manager → Image → Add → Add from URL
-
Image name:
postgres -
Tag:
16-alpine -
Click Add
-
Go to Container → Create
-
Select
postgres:16-alpine -
Configuration:
- Container name:
opencodehub-postgres - Enable auto-restart: Yes
- Network: Use the same bridge network as other containers
- Environment variables:
POSTGRES_USER=opencodehubPOSTGRES_PASSWORD=<generate-strong-password>POSTGRES_DB=opencodehub
- Volume settings:
/volume1/opencodehub/postgres → /var/lib/postgresql/data
- Port settings:
Local port: 5432 → Container port: 5432
- Container name:
-
Click Done
Using SSH (Alternative):
Section titled “Using SSH (Alternative):”ssh admin@your-synology-ipsudo -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-alpineStep 1.4: Set Up Redis
Section titled “Step 1.4: Set Up Redis”Using Container Manager:
- Pull
redis:7-alpine - Create container:
- Name:
opencodehub-redis - Environment:
REDIS_PASSWORD=<strong-password>
- Command:
redis-server --appendonly yes --requirepass YOUR_PASSWORD - Volume:
/volume1/opencodehub/redis → /data
- Port:
6379→6379
- Name:
Or via SSH:
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_PASSWORDStep 1.5: Deploy OpenCodeHub
Section titled “Step 1.5: Deploy OpenCodeHub”Option A: Pre-built Image (Fastest)
Section titled “Option A: Pre-built Image (Fastest)”If using the published Docker image:
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:latestNote: On Synology,
host.docker.internalmay not work. Use your NAS IP address instead (e.g.,192.168.1.100).
Option B: Build from Source
Section titled “Option B: Build from Source”- 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- Save this as
docker-compose.ymlin/volume1/docker/OpenCodeHub/ - Clone the repo to that folder first:
Terminal window cd /volume1/dockergit clone https://github.com/swadhinbiswas/OpencodeHub.git - In Container Manager → Project → Create
- Select the path
/volume1/docker/OpenCodeHub - Click Create
Step 1.6: Configure Reverse Proxy (Synology)
Section titled “Step 1.6: Configure Reverse Proxy (Synology)”- Control Panel → Login Portal → Advanced → Reverse Proxy
- Click Create
- General:
- Source:
- Protocol: HTTPS
- Hostname:
git.yourddns.net - Port: 443
- Destination:
- Protocol: HTTP
- Hostname:
localhost - Port: 4321
- Source:
- Custom Header → Create → WebSocket
- Header name:
Upgrade - Value:
$http_upgrade - Header name:
Connection - Value:
upgrade
- Header name:
- Click Save
Step 1.7: SSL Certificate (Let’s Encrypt)
Section titled “Step 1.7: SSL Certificate (Let’s Encrypt)”-
Control Panel → Security → Certificate
-
Click Add → Add a new certificate
-
Select Get a certificate from Let’s Encrypt
-
Domain name:
git.yourddns.net -
Email: your-email@example.com
-
Click Apply
-
After issuance, go to Configure and assign the certificate to:
git.yourddns.net:443(your reverse proxy)
Part 2: TrueNAS SCALE Deployment
Section titled “Part 2: TrueNAS SCALE Deployment”TrueNAS SCALE has native Kubernetes support with Helm charts, but Docker is easier via Apps (Docker Compose).
Step 2.1: Create Datasets
Section titled “Step 2.1: Create Datasets”- Go to Storage → Pools → Your pool → Add Dataset
- Create a parent dataset:
opencodehub - Under it, create:
reposstoragesshcachepostgresredis
Step 2.2: Deploy via Custom App (Docker Compose)
Section titled “Step 2.2: Deploy via Custom App (Docker Compose)”- Go to Apps → Discover Apps → Custom App
- Enable Advanced Mode
- 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: bridgeReplace
YOURPOOLwith your actual pool name andYOUR_PASS/YOUR_SECRETwith your values.
- Click Save
- TrueNAS will deploy all containers
Step 2.3: Configure TrueNAS Certificate
Section titled “Step 2.3: Configure TrueNAS Certificate”- System → General → GUI SSL Certificate
- Or use Apps → Certificates for app-specific SSL
- For external access, use TrueNAS’s built-in ACME (Let’s Encrypt) or upload your own certificate
Step 2.4: Reverse Proxy with Nginx Proxy Manager (Recommended)
Section titled “Step 2.4: Reverse Proxy with Nginx Proxy Manager (Recommended)”Install Nginx Proxy Manager from the TrueNAS Apps catalog:
- Apps → Discover Apps → Search “Nginx Proxy Manager”
- Install with default settings
- Access Nginx Proxy Manager at
your-nas-ip:81 - 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
- Domain Names:
Part 3: QNAP QTS Deployment
Section titled “Part 3: QNAP QTS Deployment”Step 3.1: Install Container Station
Section titled “Step 3.1: Install Container Station”- Open App Center
- Search for Container Station
- Click Install
Step 3.2: Create Folders
Section titled “Step 3.2: Create Folders”- Open File Station
- Create folder:
opencodehub - Inside it create:
repos,storage,ssh,cache,postgres,redis
Step 3.3: Deploy via Container Station
Section titled “Step 3.3: Deploy via Container Station”Create Network:
Section titled “Create Network:”- Container Station → Networks → Create
- Name:
opencodehub-network - Driver: Bridge
Create PostgreSQL:
Section titled “Create PostgreSQL:”- Create → Search Docker Hub →
postgres:16-alpine - Click Install
- Configuration:
- Name:
opencodehub-postgres - Network:
opencodehub-network - Environment:
POSTGRES_USER=opencodehubPOSTGRES_PASSWORD=<password>POSTGRES_DB=opencodehub
- Shared Folders:
/share/Container/opencodehub/postgres → /var/lib/postgresql/data
- Port:
5432
- Name:
Create Redis:
Section titled “Create Redis:”- Search and install
redis:7-alpine - Name:
opencodehub-redis - Network:
opencodehub-network - Command:
redis-server --appendonly yes --requirepass YOUR_PASS - Shared Folders:
/share/Container/opencodehub/redis → /data
Create OpenCodeHub:
Section titled “Create OpenCodeHub:”- Search and install
swadhinbiswas/opencodehub:latest - Name:
opencodehub - Network:
opencodehub-network - Environment variables (same as Synology example)
- 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
- Ports:
4321,2222
Step 3.4: QNAP Reverse Proxy
Section titled “Step 3.4: QNAP Reverse Proxy”- Control Panel → System → Reverse Proxy
- Click Create
- Rule:
- Name:
OpenCodeHub - Source Protocol: HTTPS
- Source URL:
git.yourdomain.com - Port: 443
- Destination Protocol: HTTP
- Destination URL:
localhost - Port: 4321
- Name:
- Enable HSTS
Step 3.5: SSL Certificate
Section titled “Step 3.5: SSL Certificate”- Control Panel → Security → Certificate & Private Key
- Click Replace Certificate
- Choose Get from Let’s Encrypt
- Enter your domain and email
- Click Apply
Part 4: Generic NAS / Any Docker Host
Section titled “Part 4: Generic NAS / Any Docker Host”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:
# Connect to your NAS via SSH, then run:curl -sSL https://raw.githubusercontent.com/swadhinbiswas/OpencodeHub/main/install.sh | bashUsing Docker Compose (Manual Setup)
Section titled “Using Docker Compose (Manual Setup)”If you prefer to deploy manually via Portainer or docker-compose.yml:
# Create unified data directorymkdir -p ~/opencodehub-data
# Create docker-compose.ymlcat > ~/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: bridgeEOF
# Deploycd ~/opencodehubdocker-compose up -dStep 5: Router Port Forwarding
Section titled “Step 5: Router Port Forwarding”For external access, forward these ports on your router:
| External Port | Internal IP | Internal Port | Purpose |
|---|---|---|---|
| 80 | Your NAS IP | 80 | HTTP (for Let’s Encrypt/redirect) |
| 443 | Your NAS IP | 443 | HTTPS (OpenCodeHub web) |
| 2222 | Your NAS IP | 2222 | SSH Git (optional) |
Security Note: If using a reverse proxy, you only need to forward 80 and 443. Port 4321 should NOT be exposed externally.
Step 6: Dynamic DNS (DDNS)
Section titled “Step 6: Dynamic DNS (DDNS)”If you don’t have a static IP:
Synology:
Section titled “Synology:”- Control Panel → External Access → DDNS
- Click Add
- Service Provider: Synology, No-IP, DuckDNS, etc.
- Enter hostname:
git.yourddns.net - Click Test Connection → OK
TrueNAS:
Section titled “TrueNAS:”- Network → Global Configuration → Nameservers
- Use Cloudflare or your DNS provider’s API for dynamic updates
- Or install a DDNS client as a custom app
- Control Panel → Network & File Services → DDNS
- Click Add
- Select provider and configure
Router DDNS:
Section titled “Router DDNS:”Most routers (UniFi, ASUS, TP-Link) have built-in DDNS. Configure it to update git.yourddns.net automatically.
Step 7: Create Admin User
Section titled “Step 7: Create Admin User”# Synology/QNAP/Genericssh admin@your-nas-ipdocker exec -it opencodehub bun run scripts/seed-admin.ts
# TrueNASkubectl exec -it deployment/opencodehub -- bun run scripts/seed-admin.tsEnter username, email, and password.
Step 8: Initial Setup & Verification
Section titled “Step 8: Initial Setup & Verification”- Visit
https://git.yourddns.net(or your domain) - Log in with admin credentials
- Create your first organization
- Test Git over HTTPS:
Terminal window git clone https://git.yourddns.net/admin/test-repo.git
Maintenance
Section titled “Maintenance”Update OpenCodeHub
Section titled “Update OpenCodeHub”cd ~/opencodehub # or /volume1/docker/OpenCodeHub, etc.docker-compose pulldocker-compose up -dBackup Strategy
Section titled “Backup Strategy”Automated Backup (Synology):
Section titled “Automated Backup (Synology):”- Hyper Backup → Create → Local/Remote
- Select
opencodehubshared folder - Schedule: Daily at 2 AM
- Retention: Keep last 7 versions
Manual Backup:
Section titled “Manual Backup:”# Backup script#!/bin/bashDATE=$(date +%Y%m%d_%H%M%S)BACKUP_DIR="/path/to/backups"
# Databasedocker exec opencodehub-postgres pg_dump -U opencodehub opencodehub | gzip > $BACKUP_DIR/och-db-$DATE.sql.gz
# Filestar czf $BACKUP_DIR/och-files-$DATE.tar.gz /path/to/opencodehub/repos /path/to/opencodehub/storage
# Keep only last 7 daysfind $BACKUP_DIR -name "och-*" -mtime +7 -deleteMonitor Resources
Section titled “Monitor Resources”| NAS | Monitoring Tool |
|---|---|
| Synology | Resource Monitor widget |
| TrueNAS | Reporting → CPU/Memory/Disk |
| QNAP | Resource 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
Troubleshooting
Section titled “Troubleshooting”| Problem | Solution |
|---|---|
| Container won’t start | Check logs: docker logs opencodehub. Often a database connection issue. |
| ”host.docker.internal” not found | Use your NAS’s LAN IP (e.g., 192.168.1.100) instead of host.docker.internal. |
| Permission denied on volumes | Ensure the Docker user has read/write access to the shared folders. On Synology, set permissions for the Docker group. |
| Slow performance | NAS devices often have slow CPUs. Ensure you have at least 4GB RAM. Consider using SSD for the postgres volume. |
| SSL certificate errors | Ensure your domain resolves correctly. Check DDNS is updating your IP. |
| Git SSH not connecting | Port 2222 must be forwarded on router. Some ISPs block port 22/2222. Try a different high port (e.g., 8022). |
| Database corruption after power loss | PostgreSQL with default settings can corrupt on unclean shutdown. Use a UPS. For extra safety, add fsync=on to PostgreSQL config. |
| Out of memory | Synology/QNAP with 2GB RAM will struggle. Close unused packages. Add a swap file if needed. |
NAS-Specific Tips
Section titled “NAS-Specific Tips”Synology
Section titled “Synology”- 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
TrueNAS SCALE
Section titled “TrueNAS SCALE”- 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
Next Steps
Section titled “Next Steps”- Configure Email (SMTP)
- Set up Offsite Storage (S3/R2) — highly recommended for NAS
- Enable Branch Protection
- Set up your First Stack