Install Portainer on a Linux VPS
Portainer is a web UI for Docker. Instead of driving everything from SSH, you see containers, images, volumes and Docker Compose stacks in a dashboard, with buttons to start, stop, read logs or deploy a Compose file. The project is open source: the code lives in the official GitHub repository.
This guide covers Portainer Community Edition (CE), the free edition. It works well on a personal VPS or a small lab. The official UI is English-only, so the labels in the screenshots match what you will see after install.
When you finish, you will have:
- a Portainer container that Docker restarts on its own
- an administrator account protected by a password
- local Docker already detected and ready to manage in the browser
- port
9443limited to your IP, with8000and9000left closed
This is the dashboard once local Docker is connected: left menu, top bar, environment info, and the counters in the middle (stacks, containers, images, volumes, networks).
The plan
If Docker is already running on the VPS, it comes down to five moves:
- Create the
portainer_datavolume, then start the official container. - Open
https://xxxx:9443/in the browser (self-signed certificate on the first visit). - Read the setup token from the logs and create the admin user within five minutes.
- Click Get Started to stay on local Docker.
- Restrict port
9443: Portainer talks to Docker with the same power as root.
Prerequisites
Before you paste the commands:
- you are logged in as root on a BoxToPlay Linux VPS, typically Ubuntu 24.04 or Debian 12 and newer
- Docker is already working. If it is not, start with Install Docker on Linux, a practical getting-started guide
- TCP port 9443 is not already used by another service
- you can allow TCP port 9443 in the hardware firewall of your BoxToPlay client area, only from your IP, before starting Portainer
Docker should come from the official repository, not from an Ubuntu snap package. Portainer advises against snap, and our Docker guide already uses the get.docker.com sequence.
Step 1: start Portainer
First create the volume that stores Portainer’s internal database (users, settings, history). Without it, a plain docker rm also wipes the admin account.
docker volume create portainer_data
Explicitly download the latest LTS image so Docker does not reuse an older version left in its cache:
docker pull portainer/portainer-ce:lts
Then start the official image with the lts tag, not latest. That is Portainer’s current recommendation for a server.
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:lts
Compared with the official docs, we simplify three points:
- we do not publish port
8000. It is the tunnel for Edge agents. On a single VPS that only manages its own Docker, you do not need it - we do not publish HTTP port
9000by default. Normal access is HTTPS on 9443. Port9000only exists for old bookmarks /var/run/docker.sockis mounted read-write, as in the official procedure. A:romount would break creating containers from the UI
Check that the container is Up:
docker ps --filter name=portainer
Example output:
CONTAINER ID IMAGE STATUS PORTS NAMES
a1b2c3d4e5f6 portainer/portainer-ce:lts Up 8 seconds 8000/tcp, 9000/tcp, 0.0.0.0:9443->9443/tcp, [::]:9443->9443/tcp portainer
The 8000/tcp and 9000/tcp entries without 0.0.0.0 are ports exposed by the image, not published on the VPS. They are not listening on the internet. Only 9443 is actually open, including IPv6 if Docker maps it.
If you really need legacy HTTP as well as HTTPS, add -p 9000:9000 to the docker run. That is not the path we recommend.
Step 2: create the first administrator
Open this URL in the browser:
https://xxxx:9443/
Replace xxxx with the public IP or DNS name of your VPS. On the first load, the browser shows a certificate warning: Portainer generates a self-signed certificate until you provide a real one. That is expected. Continue only if you are on your machine.
A brand-new Portainer CE instance requires a setup token. Without it, anyone who hits port 9443 in the first minutes could claim the admin account. The token is one-time use, only to create the first user or restore a backup.
Print it from the logs:
docker logs portainer
Look for setup_token=. Copy only the long hex string that follows, nothing else. The official setup token FAQ describes the same reflex.
You have five minutes to create the user. After that, Portainer refuses setup for security reasons. If that happens, use the collapsible section at the bottom of this article: restarting the container issues a new token.
The screen looks like this. The password must be at least 12 characters. The suggested username is admin; you can change it.
Enter the password twice, paste the setup token, then click Create user. Never commit that password in a repository, a ticket or a Discord channel.
Step 3: stay on local Docker
Right after that, the Environment Wizard opens. Portainer has already seen the VPS Docker socket. On a single server, click Get Started. Add Environments is for extra hosts (agent, Kubernetes, cloud). You do not need it here. That screen appears only once: the next login opens Home directly.
You then land on Home. The environment is named local, status Up, and the URL shown is the Unix socket /var/run/docker.sock. Click that card to open the Docker dashboard.
Step 4: containers and stacks
The left menu covers day-to-day work:
- Containers: list, start/stop, logs, console
- Images: what is already pulled
- Volumes and Networks
- Stacks: deploy a Docker Compose file
Right after install, the container list often shows only Portainer itself:
Stacks start empty. The simple path: Add stack, a name (for example web), paste the Compose file in the editor, then Deploy the stack. Git and upload are there too if you prefer them.
A minimal example to check that a web deploy works. It makes Nginx available only from the VPS itself at 127.0.0.1:8080. To expose it to the internet, explicitly choose a public port mapping and protect that port in the BoxToPlay hardware firewall.
services:
web:
image: nginx:alpine
ports:
- "127.0.0.1:8080:80"
restart: unless-stopped
Once deployed, stack web shows up under Stacks, and the container is usually named web-web-1 in Containers. Start, stop and logs stay in the UI, with no extra docker compose over SSH.
Security: treat Portainer like root access
Mounting docker.sock is not a detail. Anyone who can log into Portainer can, in practice, start any container, mount the host disk and become root on the VPS. The admin password is not “one more login”: it is the key to the machine.
Configure the BoxToPlay hardware firewall before docker run, then allow 9443/tcp only from your IP, never from 0.0.0.0/0. Check the IPv6 rule as well if your VPS has an IPv6 address. Complete setup immediately afterwards instead of leaving Portainer open “for later”.
A port published by Docker can bypass classic UFW rules. A command such as ufw allow 9443/tcp would also allow every source instead of limiting access to your IP. Likewise, a rule appended to the iptables INPUT chain does not correctly filter traffic forwarded to a Docker container.
For an additional restriction directly on the VPS, use the DOCKER-USER chain with the actual source IP and network interface. This is an advanced configuration that depends on the server network, so do not blindly paste a generic rule. The BoxToPlay hardware firewall remains the simplest way to restrict access before the first start.
Do not publish 8000 until you actually run Edge agents, and do not share the Portainer URL, even “just for the install”. Portainer already has web authentication: extra reverse-proxy Basic Auth is not required. It still helps if you want a DNS name and a proper Let’s Encrypt certificate.
Optional HTTPS reverse proxy with Nginx
If you prefer https://portainer.xxxx/ instead of port 9443 directly on the server IP, put Nginx (or Apache) in front with a valid certificate, and proxy to https://127.0.0.1:9443. Recreate Portainer with -p 127.0.0.1:9443:9443 so only the reverse proxy can reach that port, then let Nginx listen on 443.
Remember that Portainer’s built-in certificate is self-signed: depending on the proxy, you will either give Portainer a real certificate or tell the backend to accept that internal one. The goal is not three layers of auth. It is one clean URL and one exposed port.
Updates and backups
Durable data lives in the portainer_data volume. To update:
docker pull portainer/portainer-ce:lts
docker stop portainer
docker rm portainer
Then run exactly the same docker run as at install (same ports, same volumes, same lts tag). Do not recreate the volume: accounts and settings stay.
For a manual backup, stop the container and archive the volume, or snapshot the VPS from the BoxToPlay client area before a major upgrade. The named portainer_data volume survives docker rm, including with the -v option. The installation is only erased if you explicitly remove that volume, for example with docker volume rm portainer_data after removing the container.
The initial setup timed out
If you see a timed out for security purposes message, the five-minute window is gone. Restart the container, read the logs again, and use the new setup_token:
docker stop portainer
docker start portainer
docker logs portainer
Do not reuse the old token. Recreate the admin immediately, still within five minutes.
What next
Portainer does not replace backups, the firewall or OS updates. It is useful every day, and dangerous if left open on the internet.
If you want a Linux VPS delivered with root access, ready for Docker, with a hardware firewall in the client area, you can start your server at BoxToPlay.






More Articles
Block ads on all your devices: 4 solutions for a Linux VPS
August 18, 2026Linux VPS: Essential Commands to Get Started
August 06, 2026BoxToPlay Partner Program
July 22, 2026Install a VPN on a Linux VPS: WireGuard vs OpenVPN
July 19, 2026