# CasaOS New App Deployment Workflow ## Target: casa VM (192.168.122.33) on pre ### Prerequisites - SSH access: `ssh pre` then `ssh casaos` (or `ssh -J pre casaos`) - Sudo password: same as user password - Cloudflare API token and zone ID in `settings/credentials.env` - NPM access on linode via API --- ## Step 1: Research the Docker Image - Find the official or linuxserver.io image - Note: default port, required volumes, environment variables - Check dashboard-icons for app icon: `https://cdn.jsdelivr.net/gh/homarr-labs/dashboard-icons/webp/.webp` ## Step 2: Check Casa for Port Conflicts ```bash ssh pre "ssh casaos 'echo happy2026 | sudo -S ss -tlnp | grep LISTEN'" ``` Current port map: | Port | Service | |---|---| | 80 | CasaOS gateway | | 3000 | ConvertX | | 8080 | OmniTools | | 8443 | Code Server | | 8888 | Dozzle | ## Step 3: Create Docker Compose ```bash ssh pre "ssh casaos 'mkdir -p ~/docker/'" ``` Template (`~/docker//docker-compose.yml`): ```yaml name: services: : image: : container_name: environment: - PUID=1000 - PGID=1000 - TZ=America/Chicago labels: icon: https://cdn.jsdelivr.net/gh/homarr-labs/dashboard-icons/webp/.webp volumes: - /DATA/AppData/:/config ports: - : restart: unless-stopped x-casaos: author: self category: self hostname: .snsnetlabs.com icon: https://cdn.jsdelivr.net/gh/homarr-labs/dashboard-icons/webp/.webp index: / is_uncontrolled: false port_map: "" scheme: https store_app_id: title: custom: "" en_us: ``` ## Step 4: Deploy Container ```bash ssh pre "ssh casaos 'echo happy2026 | sudo -S mkdir -p /DATA/AppData/ && \ echo happy2026 | sudo -S chown -R 1000:1000 /DATA/AppData/ && \ cd ~/docker/ && echo happy2026 | sudo -S docker compose up -d'" ``` ## Step 5: Register with CasaOS Dashboard ```bash ssh pre "ssh casaos 'echo happy2026 | sudo -S mkdir -p /var/lib/casaos/apps/ && \ echo happy2026 | sudo -S cp ~/docker//docker-compose.yml /var/lib/casaos/apps//'" ``` ## Step 6: Create Cloudflare A Record ```bash curl -s -X POST "https://api.cloudflare.com/client/v4/zones/d4c9b425bad556070dc80848cb58e3ad/dns_records" \ -H "Authorization: Bearer AYLGpIUaw-6GvlzAltkttKp-nh3JWEVXtWuJbGvl" \ -H "Content-Type: application/json" \ --data '{"type":"A","name":".snsnetlabs.com","content":"172.238.163.85","ttl":1,"proxied":false}' ``` ## Step 7: Create NPM SSL Certificate ```bash # From linode (via pre): TOKEN=$(curl -s -X POST http://localhost:81/api/tokens \ -H "Content-Type: application/json" \ -d '{"identity":"samueljamesinc@gmail.com","secret":"Happy2025!"}' | python3 -c "import sys,json; print(json.load(sys.stdin)['token'])") curl -s -X POST http://localhost:81/api/nginx/certificates \ -H "Authorization: Bearer $TOKEN" \ -H "Content-Type: application/json" \ -d '{ "provider": "letsencrypt", "nice_name": ".snsnetlabs.com", "domain_names": [".snsnetlabs.com"], "meta": { "dns_challenge": true, "dns_provider": "cloudflare", "dns_provider_credentials": "dns_cloudflare_api_token=AYLGpIUaw-6GvlzAltkttKp-nh3JWEVXtWuJbGvl" } }' # Note the returned cert ID ``` ## Step 8: Create NPM Proxy Host ```bash curl -s -X POST http://localhost:81/api/nginx/proxy-hosts \ -H "Authorization: Bearer $TOKEN" \ -H "Content-Type: application/json" \ -d '{ "domain_names": [".snsnetlabs.com"], "forward_host": "192.168.122.33", "forward_port": , "forward_scheme": "http", "access_list_id": 0, "certificate_id": , "ssl_forced": false, "caching_enabled": true, "block_exploits": false, "allow_websocket_upgrade": true, "http2_support": false, "hsts_enabled": false, "hsts_subdomains": false, "meta": { "dns_challenge": true, "dns_provider": "cloudflare", "dns_provider_credentials": "# Cloudflare API token\ndns_cloudflare_api_token=AYLGpIUaw-6GvlzAltkttKp-nh3JWEVXtWuJbGvl" } }' ``` ## Step 9: Verify ```bash curl -s -o /dev/null -w "HTTP %{http_code}\n" -L https://.snsnetlabs.com ``` --- ## Dashboard Icons Source: `https://cdn.jsdelivr.net/gh/homarr-labs/dashboard-icons/webp/.webp` Search available icons: https://github.com/homarr-labs/dashboard-icons Formats available: webp (preferred), png, svg ## Traffic Flow ``` Internet → .snsnetlabs.com → Cloudflare DNS (A record → 172.238.163.85 / linode) → linode NPM (HTTPS termination, Let's Encrypt cert via CF DNS challenge) → http://192.168.122.33: (via NetBird tunnel to casa VM) ``` ## Deployed Apps | App | Port | Domain | NPM ID | Cert ID | |---|---|---|---|---| | CasaOS | 80 | casaos.snsnetlabs.com | 39 | 48 | | ConvertX | 3000 | convertx.snsnetlabs.com | 47 | 60 | | OmniTools | 8080 | omnitools.snsnetlabs.com | 44 | 58 | | Code Server | 8443 | code.snsnetlabs.com | 45 | 55 | | Dozzle | 8888 | dozzle.snsnetlabs.com | 46 | 59 |