a simple homelab
I've tried writing this post a dozen times now and I think I'll go with the most simplistic route of just giving a high level overview. You can ask questions or Google your heart out to find the missing pieces. The purpose of this document is to inspire you to build a homelab, not a full step-by-step so here we go....
Proxmox is a free, enterprise grade, open-source virtualization platform that allows you to run multiple virtual machines on a single host machine. This is a great way to experiment with different operating systems and software without having to dedicate a physical machine to each one. Docker is a containerization platform that allows you to package an application with all of its dependencies into a self-contained unit. This makes it easy to deploy and run applications consistently across different environments. OpenMediaVault is a network-attached storage (NAS) solution that allows you to create a centralized storage pool for your data.
By combining these three technologies, you can create a powerful and versatile homelab that can be used for a variety of purposes. For example, you could use Proxmox to run a virtual machine for your Ghost blog, a virtual machine for a web server, and a virtual machine for a media server like Plex. You could then use Docker to deploy containers for additional services, such as a database or a development environment. Finally, you could use OpenMediaVault to create a centralized storage pool for your data with NFS or SMB, such as your blog posts, media files, and backups.
Links

Proxmox - Virtualization

Docker - Containerization

Portainer - Kubernetes and Docker Management

Proxmox Helper Scripts to Launch Servers Quickly

OpenMediaVault - Network Attached Storage

Ghost - Content Management
Get Started
I am building this on a 12 year old Dell Optiplex 7010 with an i7 CPU, 12 Gb RAM, and a 240Gb SSD. It's not much, but it'll more than get the job done and get you on your way to building a new homelab or expanding your current one.
We will start off easy, but also be fully functional by the time this is done. On top of Docker we will run 3 service VM's. Nginx Proxy Manager, Ghost CMS and Watchtower. Ghost is the server we will present to the world. Nginx Proxy Manager will handle SSL offload and some security fundementals. Watchtower will keep the Docker containers updated. Docker will be managed via Portainer giving a very well polished and extensable Web UI for building your homelab. Essentially, this is what we are building:

Proxmox
Here's a tl;dr without the actual long read:
Here's a starting point for IP's and resource allocation.
hostname | ip/url | cpu | ram | disk1 | disk2 |
---|---|---|---|---|---|
pm1 | https://192.168.254.5:8006 | 8 Cores | 12Gb | 240Gb | |
ovm1 | https://192.168.254.6 | 2vCPU | 2048Gb | 32Gb | 50Gb |
docker1 | https://192.168.254.7:9443 | 2vCPU | 4096Gb | 16Gb |
Download and Install Proxmox on your hardware. Use the information presented in this post to answer as many questions as you can. This has been done a thousand times over and well documented on the internet. Proxmox's wiki is a great reference.
- Download ISO - https://enterprise.proxmox.com/iso/proxmox-ve_8.3-1.iso
- Use Etcher to copy that ISO to a USB drive - https://pve.proxmox.com/wiki/Prepare_Installation_Media & https://etcher.io/
- Use the USB drive to install Proxmox on your hardware - https://pve.proxmox.com/wiki/Installation#chapter_installation
Once you have Proxmox installed, login via the browser to the IP you set the server to. In the example here https://192.168.254.5:8006.
OpenMediaVault
Download the ISO for OpenMediaVault to your computer and upload that ISO to "local" storage on Proxmox. Use the information above as a reference. From there we install OVM via Proxmox's UI. In the example here we create a VM with the OVM ISO using mostly defaults with 2vCPU Cores, 2Gb RAM and a single 32Gb Disk. You can create the 2nd 50Gb Disk for NFS here as well. Then we login to OVM's UI, do updates, change any settings we need to (timezone, password, IP, etc.). Then we provision the 2nd disk as an ext4 filesystem, create a /docker shared folder and finally expose that shared folder via NFS.
- Download OVM ISO - https://sourceforge.net/projects/openmediavault/files/iso/7.0-32/openmediavault_7.0-32-amd64.iso
- Upload the OVM ISO to Proxmox via the Proxmox UI
- Create a new VM via the Proxmox UI with the following: 2vCPU Cores, 2Gb RAM, 2 Disks (1st a 32Gb for the OS and a 2nd 50Gb for NFS)
- Login to the OVM UI and make your settings changes, run updates and do a final reboot before starting the rest.
- Create an ext4 filesystem on the 50Gb disk.
- Create a /docker shared folder
- Expose the /docker shared folder via NFS with the following: client - 192.168.254.0/24, permission - read/write, extra options - subtree_check,insecure,no_root_squash. Click Save, then Apply.
Ubuntu 24.04 LXC w/ Docker
For this step, we'll be using Proxmox VE Helper-Scripts to install an Ubuntu 24.04 LTS LXC (linux container) that installs Docker and Portainer for us. There's a few modifications we need make in addition to deploying the LXC like modifying the LXC conf file on the Proxmox Host, permissions related settings on the LXC guest, and then the NFS client setup. After that we'll be able to deploy some Docker containers and start having fun.
- From your computer go to https://community-scripts.github.io/ProxmoxVE/scripts?id=docker and copy the .sh script URL to your clipboard and paste it into the Proxmox Console (I recommend opening a new console or using SSH on the Proxmox host) and paste the .sh script URL. This will kick off an installer script prompt that you'll need to answer.
I rarely go with defaults for this for some reason so here's what I do:
Select Advanced Then...
- Container: Priviliged
- Hostname: docker1
- Disk size: 8Gb
- CPU: 2
- RAM: 2
- Network: vmbr0
- IP Address: 192.168.254.6/24 #make this your IP
- Gateway: 192.168.254.254 #make this your default GW
- Disable IPv6: yes
- DNS Search Domain: blank
- DNS Server IP: 1.1.1.1 #or whatever you use
- VLAN: blank
- Root SSH: yes
- Verbose Mode: no
- After your LXC Container is deployed, use the Proxmox UI to shut it down. Take note of the ID Number of the LXC Container you crated. Then from the Proxmox shell you'll need to add a line to that container's config file with this command:
echo -e "lxc.apparmor.profile = unconfined" >> /etc/pve/lxc/103.conf
#the 103 needs to be replaced with your ID Number of the LXC you created. - Now under that LXC in the Proxmox UI, you'll want to go to Options --> Features and check NFS, Fuse and ensure Nesting is also checked. Save and start the CT.
- Login to the Docker server with SSH
- Create a new user with useradd dockeradmin
- Set the password with passwd dockeradmin
- Add that user to the /etc/sudoers file with the following syntax:
visudo /etc/sudoers
dockeradmin ALL=(ALL) ALL
control X
Y
Enter
- Run the following commands:
apt update && apt upgrade -y
apt install curl gpg nfs-common -y
mkdir -p /opt/docker
- Modify the /etc/fstab to permanently mount the newly minted NFS share from OMV with the following:
echo -e "192.168.254.5:/docker /opt/docker nfs vers=4.2,rw,hard,intr 0 0" >> /etc/fstab
- Reboot the Docker server, log back in via ssh and run the command:
mount | grep nfs
If you see the mount, you are good to go onto the Portainer step.
Portainer
Portainer was installed during the LXC script process (or should have been). It's pretty easy to install if you missed that step. In Portainer, I like to use "Stacks" as it helps me keep track of the docker compose elements I run as well as modify later without the feeling of starting from scratch...or doing everything from VI/CLI.
Let's deploy our 3 stacks. Below will be 3 already modified compose.yml files that you'll copy into Portainer's Web Config under Stacks. Modify the particulars if you know what your doing. You'll notice the volumes use the previously created /opt/docker directory that is NFS mounted to OMV.
services:
app:
image: 'jc21/nginx-proxy-manager:latest'
restart: unless-stopped
ports:
- '80:80' # Public HTTP Port
- '443:443' # Public HTTPS Port
- '81:81' # Admin Web Port
environment:
DB_SQLITE_FILE: "/data/database.sqlite"
DISABLE_IPV6: 'true'
INITIAL_ADMIN_EMAIL: [email protected]
INITIAL_ADMIN_PASSWORD: reallySTRONGpassword
volumes:
- /opt/docker/npm/data:/data
- /opt/docker/npm/letsencrypt:/etc/letsencrypt
Nginx Proxy Manager Docker Compose
services:
ghost:
image: ghost:5-alpine
restart: always
ports:
- 2368:2368
environment:
database__client: mysql
database__connection__host: db
database__connection__user: root
database__connection__password: REALLYstrongPASSWORD
database__connection__database: ghost
url: https://fqdn.publicsite.tld #UPDATE THIS WITH YOUR HOST.DOMAIN.TLD
volumes:
- /opt/docker/ghost/content:/var/lib/ghost/content
db:
image: mysql:8.0
restart: always
environment:
MYSQL_ROOT_PASSWORD: REALLYstrongPASSWORD
volumes:
- /opt/docker/ghost/db:/var/lib/mysql
volumes:
ghost:
db:
Ghost w/ MariaDB Docker Compose
services:
watchtower:
image: containrrr/watchtower
volumes:
- /var/run/docker.sock:/var/run/docker.sock
command: --interval 300 # Check for updates every 5 minutes
restart: always
Watchtower Docker Compose
Comments ()