Ubuntu Server + Docker + Portainer Baseline
What this is
My standard baseline setup for a new home server:
- Ubuntu Server (headless)
- Docker (container runtime)
- Portainer (web UI for Docker)
This is the starting point for all services in my homelab.
Why I needed this
I wanted a:
- Clean, repeatable server setup
- Headless system (no GUI overhead)
- Easy way to manage containers without CLI complexity
Without this:
- Managing Docker via CLI is slower and error-prone
- Rebuilding servers becomes inconsistent
- Harder to troubleshoot and scale services
My Setup
- Runs on mini PCs (e.g. Beelink)
- Connected via Ethernet
- Accessed via SSH from main PC
- No monitor/keyboard after setup
- Used as base for:
- Jellyfin
- Home Assistant
- Paperless-ngx
- Dozzle
- DIUN
Setup
1. Create Ubuntu Bootable USB
Download Ubuntu Server ISO
- Go to:
👉 https://ubuntu.com/download/server - Download latest LTS version
Create bootable USB (Windows)
Using balenaEtcher:
- Insert USB drive
- Open Balena Etcher
- Select:
- ISO file
- USB drive
- Click Flash
USB Size Requirement
- Minimum: 4 GB
- Recommended: 8 GB+ (more reliable)
2. Install Ubuntu Server
Boot from USB and follow installer:
- Use keyboard:
- Arrow keys
- Tab
- Space
Key selections:
- Network: Auto (DHCP)
- Proxy: Skip
- Storage:
- ✅ Use entire disk
- ⚠️ Select correct drive (e.g. NVMe)
- Profile:
- Username
- Password
- Server name
Important:
- ✅ Install OpenSSH Server
- ❌ Skip Ubuntu Pro
- ❌ Skip preinstalled packages (Docker etc.)
3. First Boot
Login locally or via SSH.
Find IP:
ip a
4. Update System
sudo apt update
sudo apt upgrade -y
sudo apt upgrade -y
5. Connect via SSH
From your PC:
ssh username@SERVER_IP
Accept fingerprint and log in.
👉 After this, disconnect monitor/keyboard.
6. Install Docker
curl -fsSL https://get.docker.com -o get-docker.sh
sudo sh get-docker.sh
sudo sh get-docker.sh
7. Verify Docker
sudo systemctl status docker
sudo docker run hello-world
sudo docker run hello-world
8. Install Portainer
Create volume:
sudo docker volume create portainer_data
Run container:
sudo docker run -d \
-p 9443:9443 \
--name portainer \
--restart=always \
-v /var/run/docker.sock:/var/run/docker.sock \
-v portainer_data:/data \
portainer/portainer-ce:latest
-p 9443:9443 \
--name portainer \
--restart=always \
-v /var/run/docker.sock:/var/run/docker.sock \
-v portainer_data:/data \
portainer/portainer-ce:latest
9. Access Portainer
Open browser:
https://SERVER_IP:9443
- Ignore certificate warning
- Create admin account
- Minimum 12-character password
If timeout occurs:
sudo docker restart portainer
10. Clean Up
Remove test container:
- Portainer → Containers → remove
hello-world
Remove unused images:
- Portainer → Images → delete unused
Recommendation
👉 This is my default starting point for every new server
Why:
- Fast to deploy
- Easy to manage via Portainer
- Clean base for Docker Compose stacks
- Minimal overhead (no GUI)
Verification
Confirm everything is working:
docker ps
You should see:
portainercontainer running
Access:
https://SERVER_IP:9443loads Portainer UI
Common Problems / Fixes
Cannot access Portainer
- Cause: Container not running / wrong IP
- Fix:
sudo docker ps
sudo docker restart portainer
sudo docker restart portainer
Portainer setup timed out
- Cause: Took too long creating user
- Fix:
sudo docker restart portainer
Docker command not working
- Cause: Docker not installed correctly
- Fix:
sudo systemctl restart docker
Wrong disk installed to
- Cause: Selected incorrect drive during install
- Fix:
- Reinstall Ubuntu (no easy fix)
Notes
- Portainer runs on 9443 (HTTPS)
- Always double-check disk selection during install
- This setup uses Docker CLI initially, but everything after is GUI
- Containers can be safely deleted and recreated
- Ideal next steps:
- Move to Docker Compose
- Set static IP
- Add reverse proxy (Caddy / Cloudflare)
- Configure backups to NAS
No comments to display
No comments to display