Coolify Setup: Application Deployment with Self-Hosted PaaS
Coolify installation, Docker and Git integration, application deployment, database management, SSL certificates, environment variables, and self-hosted PaaS alternative to Heroku/Netlify.
Portainer CE installation, Docker and Kubernetes management, stack deployment, volume/network management, user authorization, webhook and GitOps integration.
Portainer is an open-source container management platform that lets you manage Docker and Kubernetes environments through a web browser. Without requiring command-line knowledge, you can easily start, stop containers, view logs, and deploy stacks.
Portainer Community Edition (CE) is free and open-source. Key features:
# Create volume to store Portainer data
docker volume create portainer_data
docker run -d \
--name portainer \
--restart=always \
-p 8000:8000 \
-p 9443:9443 \
-v /var/run/docker.sock:/var/run/docker.sock \
-v portainer_data:/data \
portainer/portainer-ce:latest
After installation:
https://SERVER_IP:9443
On first login, you need to set an admin password. If you don't log in within 5 minutes, Portainer needs to be restarted for security reasons.
# portainer-compose.yml
version: '3.8'
services:
portainer:
image: portainer/portainer-ce:latest
container_name: portainer
restart: always
ports:
- "8000:8000"
- "9443:9443"
volumes:
- /var/run/docker.sock:/var/run/docker.sock
- portainer_data:/data
security_opt:
- no-new-privileges:true
volumes:
portainer_data:
docker compose -f portainer-compose.yml up -d
Portainer communicates with the Docker daemon via /var/run/docker.sock. Access to this socket provides full control over Docker:
# Check socket permissions
ls -la /var/run/docker.sock
# srw-rw---- 1 root docker 0 ... /var/run/docker.sock
# Add user to docker group (if needed)
usermod -aG docker $USER
Access to the Docker socket is equivalent to root privileges. Run Portainer on trusted networks and use a strong password.
# Example: WordPress Stack
version: '3.8'
services:
wordpress:
image: wordpress:latest
restart: always
ports:
- "8080:80"
environment:
WORDPRESS_DB_HOST: db
WORDPRESS_DB_USER: ${DB_USER}
WORDPRESS_DB_PASSWORD: ${DB_PASSWORD}
WORDPRESS_DB_NAME: wordpress
volumes:
- wordpress_data:/var/www/html
depends_on:
- db
db:
image: mysql:8.0
restart: always
environment:
MYSQL_DATABASE: wordpress
MYSQL_USER: ${DB_USER}
MYSQL_PASSWORD: ${DB_PASSWORD}
MYSQL_ROOT_PASSWORD: ${DB_ROOT_PASSWORD}
volumes:
- db_data:/var/lib/mysql
volumes:
wordpress_data:
db_data:
https://github.com/user/repoOperations available on containers from the Portainer interface:
# In Portainer interface:
# Containers → select container → Actions:
# - Start / Stop / Restart / Kill / Pause
# - Logs (real-time)
# - Console (web terminal)
# - Inspect (JSON details)
# - Stats (CPU, RAM, Network usage)
Open a terminal to a container from your web browser:
/bin/bash or /bin/sh# Commands you can run inside the container:
ls -la /app
cat /etc/nginx/nginx.conf
nginx -t
env | grep DATABASE
# From Portainer interface:
# Images → Pull Image
# Registry: docker.io (default)
# Image: nginx:latest
# To add a custom registry:
# Registries → Add Registry
# URL: registry.example.com
# Enter username and password
# From Portainer interface:
# Volumes → Add Volume
# Name: myapp_data
# Driver: local
# Volume details:
# - Which containers are using it
# - Disk usage
# - Mount point: /var/lib/docker/volumes/myapp_data/_data
# From Portainer interface:
# Networks → Add Network
# Name: myapp-network
# Driver: bridge
# Subnet: 172.20.0.0/16
# Connect containers to network:
# Container → Network → Join Network
# From Portainer interface:
# Settings → Teams → Add Team
# Team name: developers
# Add members: user1, user2
# Environments → Select Environment → Access Control
# Grant access to specific users or teams
# Role: Manager (full access) or Operator (limited)
# Create webhook for Stack or Service:
# Stack → Stack name → Webhooks
# Copy webhook URL
# Usage in GitHub Actions:
curl -X POST https://portainer.example.com/api/webhooks/WEBHOOK_TOKEN
# Usage in GitLab CI:
wget --post-data '' https://portainer.example.com/api/webhooks/WEBHOOK_TOKEN
Use Edge Agent to manage servers behind a firewall:
# In Portainer:
# Environments → Add Environment → Edge Agent
# Copy Edge ID and Edge Key
# Install Edge Agent on remote server:
docker run -d \
--name portainer_edge_agent \
--restart=always \
-v /var/run/docker.sock:/var/run/docker.sock \
-v /var/lib/docker/volumes:/var/lib/docker/volumes \
-v /:/host \
-v portainer_agent_data:/data \
-e EDGE=1 \
-e EDGE_ID=YOUR_EDGE_ID \
-e EDGE_KEY=YOUR_EDGE_KEY \
-e EDGE_INSECURE_POLL=1 \
portainer/agent:latest
# Stop and remove current container
docker stop portainer
docker rm portainer
# Pull latest image
docker pull portainer/portainer-ce:latest
# Restart (data is preserved in volume)
docker run -d \
--name portainer \
--restart=always \
-p 8000:8000 \
-p 9443:9443 \
-v /var/run/docker.sock:/var/run/docker.sock \
-v portainer_data:/data \
portainer/portainer-ce:latest
By installing Portainer on REXE servers, you can manage all your Docker containers from a single web interface. It's especially convenient for servers running multiple services.
Open port 9443 in the server firewall: 'ufw allow 9443/tcp'. Check that the container is running with 'docker ps | grep portainer'. If you want to use HTTP, also open port 9000 and add the '-p 9000:9000' parameter.
Stop the Portainer container. Reset the password with 'docker run --rm -v portainer_data:/data portainer/helper-reset-password'. The new temporary password will be shown on screen. Restart Portainer, log in with the temporary password, and set a new password.
Check Docker socket permissions: 'ls -la /var/run/docker.sock'. Make sure the Portainer container has access to the socket. If SELinux or AppArmor is active, add the ':z' or ':Z' flag for socket mount: '-v /var/run/docker.sock:/var/run/docker.sock:z'.
Make sure the container's log driver is 'json-file' or 'local'. Check with 'docker inspect CONTAINER_ID | grep LogConfig'. If the 'none' log driver is used, logs cannot be displayed. Explicitly specify the logging driver in docker-compose.yml.
Add new environments from the Environments menu. Select 'Local' for Docker on the same server. For remote servers, select 'Docker Standalone' or 'Docker Swarm' and enter the TCP endpoint (port 2375/2376). Use TLS certificates for secure connections. You can also connect to servers behind firewalls with Edge Agent.
Yes, Portainer CE offers Kubernetes support. Add your environment via Environments → Add Environment → Kubernetes by uploading your kubeconfig file or installing an agent. You can manage namespaces, deployments, services, ingresses, and pods from the web interface. However, advanced Kubernetes features may require Portainer Business Edition.
Coolify installation, Docker and Git integration, application deployment, database management, SSL certificates, environment variables, and self-hosted PaaS alternative to Heroku/Netlify.
Nextcloud installation with Docker, Apache/Nginx configuration, database setup, SSL certificate, file synchronization, app store, and performance optimization.
Uptime Kuma installation with Docker, HTTP/TCP/DNS/ping monitoring, notification integrations (Telegram, Discord, email), status page creation, and alert configuration.