Deploy with Podman
Podman is a drop-in replacement for Docker that runs without a daemon and supports rootless containers. This guide covers deploying OpenCodeHub with Podman.
Why Podman?
Section titled “Why Podman?”| Feature | Docker | Podman |
|---|---|---|
| Daemon | Required | Daemonless |
| Root access | Required by default | Rootless by default |
| Systemd integration | Limited | Native |
| Security | Good | Better (no root daemon) |
| CLI compatibility | Native | Docker-compatible |
Prerequisites
Section titled “Prerequisites”# Install Podman (Ubuntu/Debian)sudo apt updatesudo apt install -y podman podman-compose
# Install Podman (Fedora/RHEL/CentOS)sudo dnf install -y podman podman-compose
# Verify installationpodman --versionpodman-compose --versionQuick Start
Section titled “Quick Start”# Clone repositorygit clone https://github.com/swadhinbiswas/OpencodeHub.gitcd OpenCodeHub
# Copy environmentcp .env.example .env
# Start with Podman Composepodman-compose up -d
# View logspodman-compose logs -fProduction Setup (Rootless)
Section titled “Production Setup (Rootless)”1. Create User and Directories
Section titled “1. Create User and Directories”# Create dedicated user (optional but recommended)sudo useradd -r -m -d /opt/opencodehub opencodehubsudo -u opencodehub mkdir -p /opt/opencodehub/{data,postgres,redis}
# Enable lingering (keeps user services running after logout)sudo loginctl enable-linger opencodehub2. Create Pod Configuration
Section titled “2. Create Pod Configuration”Podman pods group containers like Kubernetes:
# Create a pod for all servicespodman pod create \ --name opencodehub \ --publish 3000:3000 \ --network bridge3. Create Containers
Section titled “3. Create Containers”# PostgreSQLpodman run -d \ --pod opencodehub \ --name och-postgres \ -e POSTGRES_DB=opencodehub \ -e POSTGRES_USER=opencodehub \ -e POSTGRES_PASSWORD=securepassword \ -v /opt/opencodehub/postgres:/var/lib/postgresql/data:Z \ postgres:16-alpine
# Redispodman run -d \ --pod opencodehub \ --name och-redis \ redis:7-alpine \ redis-server --requirepass redispassword
# Wait for DB to be readysleep 10
# OpenCodeHub Apppodman run -d \ --pod opencodehub \ --name och-app \ --env-file /opt/opencodehub/.env \ -v /opt/opencodehub/data:/app/data:Z \ ghcr.io/swadhinbiswas/opencodehub:latest4. Production .env
Section titled “4. Production .env”cat > /opt/opencodehub/.env << 'EOF'NODE_ENV=productionPORT=3000SITE_URL=https://git.yourcompany.com
# SecretsJWT_SECRET=your-64-char-hex-secretSESSION_SECRET=your-64-char-hex-secretINTERNAL_HOOK_SECRET=your-64-char-hex-secret
# Database (localhost because same pod)DATABASE_DRIVER=postgresDATABASE_URL=postgresql://opencodehub:securepassword@localhost:5432/opencodehub
# RedisREDIS_URL=redis://:redispassword@localhost:6379
# StorageSTORAGE_TYPE=localSTORAGE_PATH=/app/data/reposEOFSystemd Integration
Section titled “Systemd Integration”The key advantage of Podman is native systemd support.
Generate Systemd Units
Section titled “Generate Systemd Units”# Generate unit files for the podpodman generate systemd --new --files --name opencodehub
# Move to user systemd directorymkdir -p ~/.config/systemd/user/mv *.service ~/.config/systemd/user/
# Reload and enablesystemctl --user daemon-reloadsystemctl --user enable pod-opencodehub.servicesystemctl --user start pod-opencodehub.serviceVerify Service Status
Section titled “Verify Service Status”systemctl --user status pod-opencodehub.servicesystemctl --user status container-och-app.serviceAuto-start on Boot
Section titled “Auto-start on Boot”# Enable lingering for the usersudo loginctl enable-linger $(whoami)
# Now services start at boot, not loginUsing podman-compose
Section titled “Using podman-compose”If you prefer the Compose workflow:
version: '3.8'
services: app: image: ghcr.io/swadhinbiswas/opencodehub:latest ports: - "3000:3000" env_file: - .env volumes: - ./data:/app/data:Z depends_on: - postgres - redis
postgres: image: postgres:16-alpine environment: POSTGRES_DB: opencodehub POSTGRES_USER: opencodehub POSTGRES_PASSWORD: ${DATABASE_PASSWORD} volumes: - ./postgres:/var/lib/postgresql/data:Z
redis: image: redis:7-alpine command: redis-server --requirepass ${REDIS_PASSWORD}podman-compose up -dNetworking
Section titled “Networking”Using CNI Plugins
Section titled “Using CNI Plugins”# Create a dedicated networkpodman network create opencodehub-net
# Use in podpodman pod create \ --name opencodehub \ --network opencodehub-net \ --publish 3000:3000Exposing via Nginx
Section titled “Exposing via Nginx”# On host, configure Nginx to proxy to localhost:3000sudo apt install nginxSee Nginx Deployment Guide for configuration.
Updating Containers
Section titled “Updating Containers”# Pull latest imagepodman pull ghcr.io/swadhinbiswas/opencodehub:latest
# Recreate containerpodman stop och-apppodman rm och-apppodman run -d \ --pod opencodehub \ --name och-app \ --env-file /opt/opencodehub/.env \ -v /opt/opencodehub/data:/app/data:Z \ ghcr.io/swadhinbiswas/opencodehub:latestWith Systemd
Section titled “With Systemd”systemctl --user restart container-och-app.serviceTroubleshooting
Section titled “Troubleshooting”Permission Denied Errors
Section titled “Permission Denied Errors”# Fix SELinux contextsudo chcon -R -t container_file_t /opt/opencodehub/data
# Or use :Z suffix on volumes-v /path:/container/path:ZContainer Can’t Reach Database
Section titled “Container Can’t Reach Database”# In a pod, use localhost, not container namesDATABASE_URL=postgresql://user:pass@localhost:5432/dbRootless Networking Issues
Section titled “Rootless Networking Issues”# Check slirp4netns is installedsudo apt install slirp4netns
# Or use pasta (newer, faster)sudo apt install passtComparison with Docker
Section titled “Comparison with Docker”| Command | Docker | Podman |
|---|---|---|
| Run container | docker run | podman run |
| Compose | docker compose | podman-compose |
| Build image | docker build | podman build |
| View logs | docker logs | podman logs |
| Systemd units | Manual | podman generate systemd |
Most Docker commands work identically with Podman.