Introduction — what, why, how
What is pgAdmin?
pgAdmin 4 is the official, web‑based administration and development platform for PostgreSQL. It lets you browse databases, run queries, manage roles/permissions, and monitor activity from any browser.
Why run it in server mode?
Server mode centralizes access for multiple users. Each user gets their own login and saved connections, while admins can share pre‑configured server definitions and enforce policies. It’s ideal for teams and managed hosting environments.
Why containerize pgAdmin on a Plesk server?
- Isolation & portability — the app runs in its own container with a clean upgrade path.
- Easy lifecycle — pull a new image, restart, and you’re updated.
- Fits Plesk — Plesk’s Docker and Proxy Rules make it straightforward to publish the container on a subdomain with HTTPS.
How it fits together (at a glance)
- A
dpage/pgadmin4container runs on the host. - Plesk publishes it at
https://pgadmin.yourdomain.tldusing either Docker Proxy Rules (UI) or an nginx reverse proxy. - Persistent volumes store pgAdmin’s configuration and user data on the server.
- Your PostgreSQL servers remain where they are (same host, LAN, or remote) and are registered inside pgAdmin.
Prerequisites
- Plesk Obsidian with Docker extension installed.
- Root or sudo SSH access (for compose/CLI path) and Plesk admin access (for UI path).
- A subdomain ready in Plesk (e.g.,
pgadmin.example.com). - Let’s Encrypt extension in Plesk for TLS.
- Network reachability from the Plesk host to your PostgreSQL instances (open ports, firewalls, allow‑lists).
Security tip: Only expose pgAdmin over HTTPS. Consider IP allow‑lists, HTTP auth, or VPN if it’s for internal use.
Option A — Install via Plesk Docker UI (no CLI required)
- Create the subdomain in Plesk (e.g.,
pgadmin.example.com). Issue a Let’s Encrypt certificate. - Add a container: Plesk → Docker → Add Image → search for
dpage/pgadmin4and select thedpage/pgadmin4image (there’s no “official” tag in Plesk’s catalog; make sure you pick the right image and avoid similarly named variants). Choose thelatesttag unless you require a specific version → Run. - Container settings:
- Automatic start: Enable Automatic start after system reboot so pgAdmin comes back up after host reboots.
- Environment:
PGADMIN_DEFAULT_EMAIL= admin email (e.g.,admin@example.com).PGADMIN_DEFAULT_PASSWORD= strong password.- (Optional)
PGADMIN_LISTEN_PORT=80(default in the image; you can leave this as‑is). - (Optional hardening)
PGADMIN_CONFIG_ENHANCED_COOKIE_PROTECTION=True.
- Volumes (create host paths for persistence):
/var/lib/pgadmin→/srv/pgadmin/data(host)/var/log/pgadmin→/srv/pgadmin/logs(host)
- Ports:
- Disable Automatic port mapping.
- Manual mapping: map unused host ports to the container’s HTTP/HTTPS ports to avoid conflicts with Plesk’s Apache/nginx on
80/443(already in use):7980:807981:443(not required unless you configure TLS inside the container)
- We’ll publish the service on your subdomain via Plesk Proxy Rules, pointing to
http://127.0.0.1:7980.
- Start the container.
- Publish with Proxy Rules: Open the container in Plesk → Proxy Rules → map
https://pgadmin.example.comto the backendhttp://127.0.0.1:7980. - Harden access (strongly recommended):
- Enable Basic Auth (password‑protected directory) in Plesk to add an auth wall in front of pgAdmin:
- Plesk → Websites & Domains → your pgAdmin domain → Password‑Protected Directories.
- Add Protected Directory and set path
/(protect the whole site) or/adminif you proxy a sub‑path. - Add a User (this is separate from pgAdmin users). Keep the credentials in your team password manager.
- Restrict by IP where feasible (Allow from office/VPN ranges).
- Keep the Let’s Encrypt cert auto‑renewing.
- Enable Basic Auth (password‑protected directory) in Plesk to add an auth wall in front of pgAdmin:
- Log in at
https://pgadmin.example.comusing the credentials from step 3. - Register your PostgreSQL servers inside pgAdmin (hostname/IP, port, database, role). Use SSH tunnels or VPN if required by your network policy.
https://pgadmin.example.comusing the credentials from step 3. - Register your PostgreSQL servers inside pgAdmin (hostname/IP, port, database, role). Use SSH tunnels or VPN if required by your network policy.
- Start the container.
- Publish with Proxy Rules: Open the container in Plesk → Proxy Rules → map
pgadmin.example.comto the container’s port80. - Harden access (recommended):
- Plesk domain → Hosting & DNS → Apache & nginx settings → add allow‑list rules or Basic Auth if appropriate.
- Keep the Let’s Encrypt cert auto‑renewing.
- Log in at
https://pgadmin.example.comusing the credentials from step 3. - Register your PostgreSQL servers inside pgAdmin (hostname/IP, port, database, role). Use SSH tunnels or VPN if required by your network policy.
Option B — Install with docker‑compose (CLI)
Create a docker-compose.yml (as root or with sudo) and bring the service up. Then publish it through Plesk as a reverse proxy.
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
version: "3.9" services: pgadmin: image: dpage/pgadmin4:latest restart: unless-stopped environment: PGADMIN_DEFAULT_EMAIL: admin@example.com PGADMIN_DEFAULT_PASSWORD: "change-me-very-strong" PGADMIN_CONFIG_ENHANCED_COOKIE_PROTECTION: "True" TZ: "America/New_York" volumes: - /srv/pgadmin/data:/var/lib/pgadmin - /srv/pgadmin/logs:/var/log/pgadmin ports: - "5050:80" # host:container |
Bring it up:
|
1 2 3 |
mkdir -p /srv/pgadmin/{data,logs} docker compose up -d |
Publish through Plesk (reverse proxy)
- In Plesk, create/choose
pgadmin.example.comwith a Let’s Encrypt cert. - Go to Apache & nginx settings → Additional nginx directives and proxy to the local port:
|
1 2 3 4 5 6 7 8 |
location / { proxy_pass http://127.0.0.1:5050; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header X-Forwarded-Proto $scheme; } |
(Alternatively, if you also have the Docker extension, you can create Proxy Rules to the compose‑managed container by host:port.)
Post‑install checklist
- Enable Two‑Factor Authentication (2FA) for pgAdmin users: In pgAdmin, open the user menu (top‑right) → Two‑Factor Authentication → follow prompts to enroll a TOTP app (e.g., Google Authenticator, Authy, 1Password). Require all team accounts to enable 2FA.
- Change the admin password after first login if you used a temporary value.
- Backups: include
/srv/pgadmin/datain your server backups (this holds users, saved connections, preferences, etc.). - Updates: periodically pull a new image and recycle the container during a maintenance window.
- Pre‑seed servers (optional): mount a
servers.jsoninto/pgadmin4/servers.jsonto pre‑load connection definitions for users. - Email (optional): configure SMTP in pgAdmin’s preferences to enable password resets and alerts.
- Access control: consider IP allow‑lists, HTTP auth, or VPN if pgAdmin is for internal staff only.
Why these security measures (quick rationale)
- Basic Auth at the domain adds a front‑door credential prompt before pgAdmin even loads. It blocks most bot scans and credential‑stuffing noise, reduces exposure of pgAdmin endpoints, and provides defense‑in‑depth alongside pgAdmin’s own auth.
- Two‑Factor Authentication (2FA) in pgAdmin protects privileged sessions even if a password is leaked or reused. TOTP enrollment is quick and strongly recommended for all team accounts.
- SMTP configured in pgAdmin enables reliable password resets and 2FA recovery codes. Use a proper sender, relay (or transactional mail provider), and verify SPF/DKIM/DMARC for delivery.
Troubleshooting quick hits
- Can’t reach pgAdmin via the subdomain → check Plesk Proxy Rules (UI path) or nginx reverse proxy (compose path), and ensure the Let’s Encrypt cert is valid.
- Login loops or CSRF errors → ensure
proxy_set_header X-Forwarded-Proto $scheme;is present and HTTPS is used end‑to‑end. - Data not persisting → verify the
/var/lib/pgadminvolume is mounted to a writable host path. - PostgreSQL connection fails → confirm firewall rules, resolve hostnames, and verify that the DB server allows connections from the Plesk host.
Fix: “Failed to create the directory /var/lib/pgadmin/sessions: Permission denied”
pgAdmin runs as UID/GID 5050 inside the dpage/pgadmin4 container. If the host‑mounted volume isn’t writable by that user (common when the host path is owned by root), you’ll see this error.
Step 1 — Stop the container
- Plesk → Docker → your pgAdmin container → Stop.
Step 2 — Ensure host paths exist & are writable by UID 5050
Use the paths you mapped in Plesk (either /srv/pgadmin/... or your subscription vhost path). Examples:
If you used /srv/pgadmin/...:
|
1 2 3 4 |
sudo mkdir -p /srv/pgadmin/{data,logs} sudo chown -R 5050:5050 /srv/pgadmin/data /srv/pgadmin/logs sudo chmod -R u+rwX,g+rwX /srv/pgadmin/data /srv/pgadmin/logs |
If you used a subscription vhost path, e.g. /var/www/vhosts/pgadmin.acme.com/pgadmin/...:
|
1 2 3 4 5 |
sudo mkdir -p /var/www/vhosts/pgadmin.acme.com/pgadmin/{data,logs} sudo chown -R 5050:5050 /var/www/vhosts/pgadmin.acme.com/pgadmin/data \ /var/www/vhosts/pgadmin.acme.com/pgadmin/logs sudo chmod -R u+rwX,g+rwX /var/www/vhosts/pgadmin.acme.com/pgadmin/{data,logs} |
Step 3 — SELinux (if enforcing on AlmaLinux/RHEL, etc.)
Bind‑mounted directories may need a container‑friendly label since Plesk’s Docker UI can’t add :z automatically:
|
1 2 3 4 5 |
# Use the base you actually mapped sudo chcon -R -t container_file_t /srv/pgadmin # or sudo chcon -R -t container_file_t /var/www/vhosts/pgadmin.acme.com/pgadmin |
Step 4 — Start the container
- Plesk → Docker → Start.
This resolves the session directory error and lets pgAdmin create /var/lib/pgadmin/sessions inside the mounted volume.
Summary
Using the dpage/pgadmin4 container keeps pgAdmin isolated, easy to upgrade, and simple to publish securely on a Plesk server. Choose the Plesk Docker UI for a point‑and‑click experience, or docker‑compose if you prefer managing infrastructure as code. Either way, reverse‑proxy the service over HTTPS, persist the data volume, and lock down access for a reliable, team‑friendly PostgreSQL admin portal.




