Shubham Ranpise

Back

Deploying Portainer

High-level summery of why Portainer was chosen, deployment steps, compose file, permission fixes, and security notes for a homelab.

Why Portainer#

Portainer was chosen for these practical reasons:

  • Administrative UI: a clean web interface for container lifecycle management (create, update, inspect), which reduces CLI friction as the number of containers grows.
  • Operational hygiene: easier to maintain stacks, inspect volumes, networks and resource usage; useful when shifting from single-host experimentation to a managed homelab.
  • Monitoring & alerts integration: Portainer can be a centralized place to view logs, and it can integrate with external alerting / webhook systems for security notifications and automation (use webhooks or external monitoring tools for alerts).
  • Faster on-boarding: visual controls help when sharing access with collaborators or when returning to the environment after a break.

Originally the goal was minimal CLI-only stacks. That worked while the environment was tiny, but as container count grew the CLI-only workflow became restrictive. Portainer restores visibility and lowers operational overhead while still allowing scripted automation.


Deployment context#

  • Service account for deployments: iamdocker (member of the docker group)
  • Service stacks directory: /opt/dockerstacks/ (each stack in its own subfolder)
  • This stack: /opt/dockerstacks/portainer
  • Network binding: Tailscale interface at 100.111.X.X (Portainer bound to this interface to minimize admin ui exposure)

Commands#

# switch to the deployment user
sudo -u iamdocker -s
cd /opt/dockerstacks/
mkdir -p /opt/dockerstacks/portainer

# create named volume for Portainer data
docker volume create portainer_data

# ensure volume data is owned by the host UID/GID we will run the container as (iamdocker)
sudo chown -R 111:222 /var/lib/docker/volumes/portainer_data/_data
bash

Note: 111:222 corresponds to the host iamdocker UID and docker GID on this system. Adjust if UIDs/GIDs differ on other hosts.


Create docker-compose file#

Recommended tweak: consider restart: unless-stopped instead of always to avoid automatic restarts after intentional stops.



Start Portainer container#

sudo -u iamdocker -s
cd /opt/dockerstacks/portainer
docker compose pull
docker compose up -d
bash

The portainer admin ui should be acceeesible on Tailscal vpn network on port 13443.


Portainer gives the homelab improved visibility and operational hygiene while preserving scriptable deployments under /opt/dockerstacks. The current configuration balances convenience and security by restricting network exposure (Tailscale) and applying basic container hardening (no-new-privileges).