Home Network & NAS Deployment
Running PicFast on your own NAS keeps your images on hardware you control — no cloud provider, no monthly fees. This guide covers getting PicFast on common NAS platforms and exposing it to the internet when you don't have a public IP address.
Why NAS?
NAS hardware is ideal for an image hosting platform:
- Drives are already there, and storage is the whole point
- Modern NAS boxes run Docker natively
- Energy-efficient 24/7 operation
- Your data stays on your drives, on your LAN
NAS platforms
PicFast runs on any platform that supports Docker. Here are the specifics for each:
Synology
Use Container Manager (formerly Docker). Create a stack from docker-compose:
- Open Container Manager → Project → Create
- Paste the docker-compose content below, adjusting paths and secrets
- Map
/volume1/docker/picfast/uploads(or wherever your storage lives) as the data volume
QNAP
Use Container Station. Create an application from docker-compose, same as Synology. Make sure volumes point to a shared folder under /share/.
TrueNAS
Use the Apps screen with the Docker Compose option, or deploy via docker compose in a jail/VM. ZFS datasets make great volume mounts for uploads and thumbnails.
Unraid
Add a container via the Docker tab with a custom compose file. Point volumes to /mnt/user/picfast/ for parity-protected storage.
Generic Linux / Raspberry Pi
Clone the repo or use the Docker Hub image. On a Pi, use xbeta/picfast:latest (multi-arch includes ARM64).
Minimal NAS compose
Here's a lean docker-compose file for home deployment. Save as docker-compose.yml and run docker compose up -d:
services:
db:
image: postgres:16-alpine
restart: unless-stopped
environment:
POSTGRES_USER: picfast
POSTGRES_PASSWORD: picfast
POSTGRES_DB: picfast
volumes:
- pgdata:/var/lib/postgresql/data
app:
image: xbeta/picfast:latest
restart: unless-stopped
ports:
- "18080:8080"
environment:
PICFAST_DATABASE_URL: "postgres://picfast:picfast@db:5432/picfast?sslmode=disable"
PICFAST_JWT_SECRET: "replace-with-a-strong-random-value"
PICFAST_SERVER_BASE_URL: "https://your-domain.com"
PICFAST_APP_ADMIN_EMAIL: "admin@example.com"
PICFAST_APP_ADMIN_PASSWORD: "change-this-password"
PICFAST_STORAGE_LOCAL_ROOT: "/app/data/uploads"
PICFAST_STORAGE_THUMBNAIL_DIR: "/app/data/thumbnails"
volumes:
- uploads:/app/data/uploads
- thumbnails:/app/data/thumbnails
depends_on:
- db
volumes:
pgdata:
uploads:
thumbnails: Exposing to the internet
Most home networks don't have a static public IP. Even with one, opening ports on a home router is a security risk. The solution is a tunnel — an encrypted outbound connection that proxies public traffic to your local service without opening ports.
Option 1: Cloudflare Tunnel (recommended)
Cloudflare Tunnel (cloudflared) is free, stable, and requires no open ports. You need a domain with DNS managed by Cloudflare.
Setup
- Install
cloudflaredon your NAS or host - Authenticate:
cloudflared tunnel login - Create a tunnel:
cloudflared tunnel create picfast - Configure the tunnel — create
config.yml:
tunnel: <tunnel-id>
credentials-file: /home/user/.cloudflared/<tunnel-id>.json
ingress:
- hostname: pics.yourdomain.com
service: http://localhost:18080
- service: http_status:404 - Create a DNS record:
cloudflared tunnel route dns picfast pics.yourdomain.com - Start the tunnel:
cloudflared tunnel run picfast
To run it persistently, add cloudflared to your compose file as an additional service:
tunnel:
image: cloudflare/cloudflared:latest
restart: unless-stopped
command: tunnel run
environment:
TUNNEL_TOKEN: "<your-tunnel-token>" Cloudflare Tunnel provides DDoS protection, free SSL, and caching. However, Cloudflare proxies your traffic — they see the data in transit. If you need end-to-end privacy, use Tailscale instead.
Option 2: Tailscale
Tailscale creates a WireGuard-based mesh network between your devices. It has two modes for exposing services:
Tailscale Serve (LAN-only, no public exposure)
Exposes a service within your tailnet. Other Tailscale users on your network can access it via a *.ts.net name:
tailscale serve --bg 18080 Now your PicFast instance is at https://<node-name>.tailnet-name.ts.net — but only for other devices on your tailnet. Good for private family use.
Tailscale Funnel (public internet)
Funnel extends Tailscale Serve to the public internet. Any device on the internet can reach your service:
tailscale serve --bg 18080
tailscale funnel --bg 18080 Funnel has limits — 443 only, bandwidth caps on the free plan. But it's dead simple and requires zero DNS configuration.
Option 3: FRP (Fast Reverse Proxy)
FRP is widely used in China for 内网穿透 where Cloudflare and Tailscale may be slow or unavailable. It requires a separate VPS as a relay server.
Server side (VPS with public IP)
# frps.toml
bindPort = 7000
vhostHTTPPort = 8080 Client side (your NAS, behind NAT)
# frpc.toml
serverAddr = "<vps-ip>"
serverPort = 7000
[[proxies]]
name = "picfast-web"
type = "http"
localPort = 18080
customDomains = ["pics.yourdomain.com"] The VPS receives traffic on port 8080 and relays it through the outbound tunnel to your NAS. FRP is fast, but you need to manage the VPS, handle SSL termination yourself (via Nginx or Caddy on the VPS), and pay for the server.
Comparing tunnel options
| Cloudflare Tunnel | Tailscale Funnel | FRP | |
|---|---|---|---|
| Public access | ✅ | ✅ | ✅ |
| Requires domain | Yes | No | Yes (for HTTPS) |
| Requires VPS | No | No | Yes |
| SSL / HTTPS | Auto | Auto | Manual (Nginx/Caddy) |
| Bandwidth | Free (fair use) | Limited on free plan | Limited by VPS |
| Privacy | Cloudflare decrypts | End-to-end encrypted | Relay server can see traffic |
| Works in China | Partial | Slow | ✅ |
| Best for | Global, production | Personal, private | China, full control |
Security notes
- Always set
PICFAST_JWT_SECRETto a strong random value - Disable guest upload (
PICFAST_APP_ALLOW_GUEST_UPLOAD=false) unless you specifically need it - Close registration after creating your accounts (
PICFAST_APP_ALLOW_REGISTRATION=false) - On first startup, the setup wizard runs at
/setup. SetPICFAST_APP_ADMIN_EMAILandPICFAST_APP_ADMIN_PASSWORDto auto-create the admin and skip the wizard for headless deployments - Configure your tunnel to enforce HTTPS — all three options above do this by default
- If using FRP on a Chinese VPS, set up file-based rate limiting (your reverse proxy handles this)