327 lines
6.5 KiB
Markdown
327 lines
6.5 KiB
Markdown
# Dokploy VM Bootstrap (Verbose Noob Walkthrough)
|
|
|
|
Purpose: set up a fresh Ubuntu VM (on Proxmox) with Docker and Dokploy for Fiddy deployment, using a copy-paste sequence with verification at each step.
|
|
|
|
Scope:
|
|
- This runbook is for a new Ubuntu VM with SSH enabled.
|
|
- It assumes Dokploy will be on its own VM.
|
|
- It does not install app containers yet; it prepares the Dokploy control plane.
|
|
|
|
Important reality:
|
|
- This Codex environment cannot directly SSH into your VM or use your credentials.
|
|
- You run the commands below on your VM and paste outputs back; I verify and guide next actions.
|
|
|
|
---
|
|
|
|
## 0) What to prepare first
|
|
|
|
Collect these values before you start:
|
|
|
|
- `VM_IP` = your Ubuntu VM LAN IP (example: `192.168.7.146`)
|
|
- `SSH_USER` = ssh username (example: `nico`)
|
|
- `SSH_PORT` = usually `22`
|
|
- `TZ` = timezone (example: `America/Los_Angeles`)
|
|
|
|
From your laptop/desktop, connect:
|
|
|
|
```bash
|
|
ssh <SSH_USER>@<VM_IP>
|
|
```
|
|
|
|
If this fails, fix SSH access first.
|
|
|
|
---
|
|
|
|
## 1) Baseline OS update and required tools
|
|
|
|
Run on VM:
|
|
|
|
```bash
|
|
sudo apt update
|
|
sudo apt -y upgrade
|
|
sudo apt -y install ca-certificates curl gnupg lsb-release ufw fail2ban jq
|
|
```
|
|
|
|
Set timezone:
|
|
|
|
```bash
|
|
sudo timedatectl set-timezone <TZ>
|
|
timedatectl
|
|
```
|
|
|
|
Verification:
|
|
- `timedatectl` shows your timezone.
|
|
- `apt` commands exit without errors.
|
|
|
|
---
|
|
|
|
## 2) Install Docker Engine (official repo)
|
|
|
|
Run on VM:
|
|
|
|
```bash
|
|
sudo install -m 0755 -d /etc/apt/keyrings
|
|
curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo gpg --dearmor -o /etc/apt/keyrings/docker.gpg
|
|
sudo chmod a+r /etc/apt/keyrings/docker.gpg
|
|
|
|
echo \
|
|
"deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.gpg] https://download.docker.com/linux/ubuntu \
|
|
$(. /etc/os-release && echo "$VERSION_CODENAME") stable" | \
|
|
sudo tee /etc/apt/sources.list.d/docker.list > /dev/null
|
|
|
|
sudo apt update
|
|
sudo apt -y install docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin
|
|
```
|
|
|
|
Enable/start Docker:
|
|
|
|
```bash
|
|
sudo systemctl enable docker
|
|
sudo systemctl start docker
|
|
sudo systemctl status docker --no-pager
|
|
```
|
|
|
|
Optional (run docker without sudo for your user):
|
|
|
|
```bash
|
|
sudo usermod -aG docker $USER
|
|
newgrp docker
|
|
docker ps
|
|
```
|
|
|
|
Verification:
|
|
- `docker ps` works.
|
|
- `docker compose version` returns version.
|
|
|
|
---
|
|
|
|
## 3) Host firewall baseline (before Dokploy)
|
|
|
|
Goal: allow SSH + HTTP/HTTPS, deny others.
|
|
|
|
Run on VM:
|
|
|
|
```bash
|
|
sudo ufw default deny incoming
|
|
sudo ufw default allow outgoing
|
|
sudo ufw allow 22/tcp
|
|
sudo ufw allow 80/tcp
|
|
sudo ufw allow 443/tcp
|
|
sudo ufw allow 3000/tcp
|
|
sudo ufw --force enable
|
|
sudo ufw status verbose
|
|
```
|
|
|
|
Notes:
|
|
- Dokploy UI is typically on `3000` for first setup.
|
|
- After reverse proxy is in place, you can restrict `3000` to LAN/VPN.
|
|
|
|
---
|
|
|
|
## 4) Install Dokploy
|
|
|
|
Run on VM:
|
|
|
|
```bash
|
|
curl -sSL https://dokploy.com/install.sh | sh
|
|
```
|
|
|
|
Check containers:
|
|
|
|
```bash
|
|
docker ps --format "table {{.Names}}\t{{.Status}}\t{{.Ports}}"
|
|
```
|
|
|
|
Open Dokploy UI from your browser:
|
|
|
|
- `http://<VM_IP>:3000`
|
|
|
|
Create initial admin account.
|
|
|
|
Verification:
|
|
- Dokploy UI loads.
|
|
- You can sign in.
|
|
|
|
---
|
|
|
|
## 5) Immediate post-install hardening
|
|
|
|
### 5.1 Keep SSH secure
|
|
|
|
Edit SSH daemon config:
|
|
|
|
```bash
|
|
sudo nano /etc/ssh/sshd_config
|
|
```
|
|
|
|
Recommended minimum:
|
|
- `PermitRootLogin no`
|
|
- `PasswordAuthentication no` (only if SSH key login already works)
|
|
- `PubkeyAuthentication yes`
|
|
|
|
Apply:
|
|
|
|
```bash
|
|
sudo systemctl restart ssh
|
|
```
|
|
|
|
### 5.2 Fail2ban basic protection
|
|
|
|
Create local jail file:
|
|
|
|
```bash
|
|
sudo tee /etc/fail2ban/jail.local > /dev/null <<'EOF'
|
|
[sshd]
|
|
enabled = true
|
|
maxretry = 5
|
|
findtime = 10m
|
|
bantime = 1h
|
|
EOF
|
|
```
|
|
|
|
Apply:
|
|
|
|
```bash
|
|
sudo systemctl enable fail2ban
|
|
sudo systemctl restart fail2ban
|
|
sudo fail2ban-client status
|
|
```
|
|
|
|
---
|
|
|
|
## 6) Dokploy first configuration (UI)
|
|
|
|
In Dokploy:
|
|
|
|
1. Create project: `fiddy`
|
|
2. Add registry credentials:
|
|
- Host: `git.nicosaya.com`
|
|
- Username: same as Gitea registry user
|
|
- Password/token: registry token
|
|
3. Create app: `fiddy-web`
|
|
- Type: Docker image
|
|
- Image: `git.nicosaya.com/nalalangan/fiddy/web:main`
|
|
- Internal port: `3000`
|
|
- Exposed host port: `3010`
|
|
- Health path: `/api/health/ready`
|
|
4. Create app: `fiddy-scheduler`
|
|
- Type: Docker image
|
|
- Image: `git.nicosaya.com/nalalangan/fiddy/scheduler:main`
|
|
- No public port
|
|
5. Enable Auto Deploy for both apps and copy both webhook URLs.
|
|
|
|
---
|
|
|
|
## 7) Gitea repo secrets required after Dokploy apps exist
|
|
|
|
In Gitea repo `Settings -> Secrets -> Actions`, set:
|
|
|
|
- `REGISTRY_USER`
|
|
- `REGISTRY_PASS`
|
|
- `DOKPLOY_DEPLOY_HOOK` (from web app in Dokploy)
|
|
- `DOKPLOY_SCHEDULER_DEPLOY_HOOK` (from scheduler app in Dokploy)
|
|
- `DOKPLOY_HEALTHCHECK_URL`
|
|
- final: `https://fiddy.nicosaya.com/api/health/ready`
|
|
- temporary allowed: `http://<VM_IP>:3010/api/health/ready`
|
|
|
|
---
|
|
|
|
## 8) First deployment flow
|
|
|
|
From your local repo:
|
|
|
|
```bash
|
|
git commit --allow-empty -m "chore: trigger dokploy first deploy"
|
|
git push origin main
|
|
```
|
|
|
|
Expected `.gitea/workflows/deploy-dokploy.yml` behavior:
|
|
1. build/push web image
|
|
2. build/push scheduler image
|
|
3. call Dokploy web hook
|
|
4. call Dokploy scheduler hook
|
|
5. wait for ready health check
|
|
|
|
Verification:
|
|
- Gitea workflow is green.
|
|
- Dokploy app logs show successful pull/start.
|
|
- Health URLs respond 200.
|
|
|
|
---
|
|
|
|
## 9) Troubleshooting quick map
|
|
|
|
- Workflow fails on registry login:
|
|
- re-check `REGISTRY_USER` and `REGISTRY_PASS`.
|
|
- Dokploy hook step fails:
|
|
- re-check hook URL secret values.
|
|
- Health check fails:
|
|
- verify app env vars (`DATABASE_URL` etc).
|
|
- verify upstream route and Nginx Proxy Manager mapping.
|
|
- verify DB reachable from VM/network.
|
|
|
|
---
|
|
|
|
## 10) Execution log template (fill as you go)
|
|
|
|
Copy/paste this section and fill values:
|
|
|
|
```md
|
|
# Dokploy VM Setup Execution Log
|
|
|
|
Date:
|
|
Operator:
|
|
VM IP:
|
|
Ubuntu version (`lsb_release -a`):
|
|
|
|
## Step 1 - OS prep
|
|
- Result:
|
|
- Notes:
|
|
|
|
## Step 2 - Docker install
|
|
- `docker --version`:
|
|
- `docker compose version`:
|
|
- Result:
|
|
|
|
## Step 3 - Firewall
|
|
- `ufw status verbose`:
|
|
- Result:
|
|
|
|
## Step 4 - Dokploy install
|
|
- Dokploy UI reachable: yes/no
|
|
- Result:
|
|
|
|
## Step 5 - Hardening
|
|
- SSH hardened: yes/no
|
|
- fail2ban status:
|
|
- Result:
|
|
|
|
## Step 6 - Dokploy apps
|
|
- Web app created: yes/no
|
|
- Scheduler app created: yes/no
|
|
- Hooks copied: yes/no
|
|
|
|
## Step 7 - Gitea secrets
|
|
- Secrets completed: yes/no
|
|
|
|
## Step 8 - First deploy
|
|
- Workflow URL:
|
|
- Result:
|
|
- Health checks:
|
|
|
|
## Issues encountered
|
|
-
|
|
|
|
## Final status
|
|
- Ready for NPM/domain wiring: yes/no
|
|
```
|
|
|
|
---
|
|
|
|
## 11) Safety notes
|
|
|
|
- Do not share raw credentials/tokens in chat or docs.
|
|
- Prefer SSH keys over passwords.
|
|
- Keep Dokploy host updated weekly (`sudo apt update && sudo apt -y upgrade`).
|
|
- Snapshot VM before major config changes.
|