{"id":51723675,"url":"https://github.com/nooblk-98/wordpress-docker-fpm-nginx","last_synced_at":"2026-07-17T15:38:59.962Z","repository":{"id":353555665,"uuid":"1219913645","full_name":"nooblk-98/wordpress-docker-fpm-nginx","owner":"nooblk-98","description":"Production-ready WordPress stack with PHP-FPM, Nginx, MariaDB and Certbot SSL fully containerized with Docker Compose","archived":false,"fork":false,"pushed_at":"2026-05-26T06:28:14.000Z","size":350,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2026-07-17T15:38:49.182Z","etag":null,"topics":["docker","docker-compose","letsencrypt","mariadb","nginx","php-fpm","ssl","wordpress","wordpress-docker"],"latest_commit_sha":null,"homepage":"","language":"Shell","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/nooblk-98.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2026-04-24T10:53:56.000Z","updated_at":"2026-05-26T06:27:20.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/nooblk-98/wordpress-docker-fpm-nginx","commit_stats":null,"previous_names":["nooblk-98/wordpress-docker-fpm-nginx"],"tags_count":2,"template":false,"template_full_name":null,"purl":"pkg:github/nooblk-98/wordpress-docker-fpm-nginx","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/nooblk-98%2Fwordpress-docker-fpm-nginx","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/nooblk-98%2Fwordpress-docker-fpm-nginx/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/nooblk-98%2Fwordpress-docker-fpm-nginx/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/nooblk-98%2Fwordpress-docker-fpm-nginx/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/nooblk-98","download_url":"https://codeload.github.com/nooblk-98/wordpress-docker-fpm-nginx/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/nooblk-98%2Fwordpress-docker-fpm-nginx/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":35587132,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-26T15:22:16.424Z","status":"online","status_checked_at":"2026-07-17T02:00:06.162Z","response_time":116,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["docker","docker-compose","letsencrypt","mariadb","nginx","php-fpm","ssl","wordpress","wordpress-docker"],"created_at":"2026-07-17T15:38:59.345Z","updated_at":"2026-07-17T15:38:59.946Z","avatar_url":"https://github.com/nooblk-98.png","language":"Shell","funding_links":[],"categories":[],"sub_categories":[],"readme":"\u003cdiv align=\"center\"\u003e\n\n# WordPress FPM + Nginx\n\n[![GitHub Repo](https://img.shields.io/badge/GitHub-wordpress--docker--fpm--nginx-181717?style=flat-square\u0026logo=github)](https://github.com/nooblk-98/wordpress-docker-fpm-nginx)\n[![License](https://img.shields.io/badge/License-MIT-yellow?style=flat-square)](LICENSE)\n\n**Multi-site WordPress hosting on a single VPS.** Nginx on the host, per-site PHP-FPM in Docker, shared MariaDB/MySQL and Redis.\n\n[Features](#features) • [Architecture](#architecture) • [Prerequisites](#prerequisites) • [Quick start](#quick-start) • [Management menu](#management-menu) • [CLI reference](#cli-reference) • [Backups](#backups) • [Troubleshooting](#troubleshooting)\n\n\u003c/div\u003e\n\n---\n\n## Features\n\n- **Multi-site** — each site gets its own PHP container and Nginx config on a single VPS\n- **Per-site PHP versions** — choose PHP 7.4, 8.0, 8.1, 8.2, 8.3, or 8.4 per site\n- **Database choice** — MariaDB or MySQL, picked during setup\n- **Automatic SSL** — Let's Encrypt via Certbot with auto-renewal\n- **One-command bootstrap** — go from a blank VPS to a running WordPress server with a single curl command\n- **SQLite state database** — all site metadata tracked locally (domains, credentials, PHP versions, ports)\n- **Automated backups** — per-site file and database backups with point-in-time restore from the menu\n- **Management menu** — 20-option interactive menu covering site management, WP updates, password reset, resource monitoring, and more\n\n## Architecture\n\nNginx runs on the host (not in Docker), handling SSL termination and proxying to per-site PHP-FPM containers. MariaDB/MySQL and Redis run as shared Docker containers.\n\n```\nHost (VPS)\n├── Nginx :80/:443  (host process)\n│   └── proxy_pass to PHP containers\n└── Docker network\n    ├── wp_php_site-a  :9001  (PHP-FPM, per site)\n    ├── wp_php_site-b  :9002  (PHP-FPM, per site)\n    ├── wp_db          :3306  (MariaDB/MySQL, shared)\n    └── wp_redis       :6379  (Redis, shared)\n```\n\nEach site gets its own PHP container with a unique port so PHP versions are isolated. If one site crashes its PHP process the others keep running.\n\nAll sites share a single MariaDB/MySQL instance with separate databases and users, and a single Redis instance for object caching.\n\n## Prerequisites\n\n- A Linux VPS (Ubuntu 22.04+ or Debian 12+ recommended)\n- Root access\n- A domain name pointed at your VPS IP (required for SSL)\n- Ports 80 and 443 open in your firewall\n\n## Quick start\n\n### One-command install\n\nRun this on a fresh VPS as root:\n\n```bash\nbash \u003c(curl -fsSL https://raw.githubusercontent.com/nooblk-98/wordpress-docker-fpm-nginx/main/install.sh)\n```\n\nThis will:\n\n1. Install git and clone the repository to `/opt/wp-manager`\n2. Run the core infrastructure setup\n3. Enable the management menu on SSH login\n4. Launch the interactive menu\n\n### Step-by-step\n\n```bash\ngit clone https://github.com/nooblk-98/wordpress-docker-fpm-nginx.git\ncd wordpress-docker-fpm-nginx\nsudo bash src/install.sh\n```\n\nDuring setup you will be prompted for:\n\n- Database engine (MariaDB or MySQL) and version\n- Database passwords (auto-generated if left blank)\n\n\u003e [!NOTE]\n\u003e The setup installs Nginx, Certbot, Docker, and starts MariaDB/MySQL + Redis containers. WordPress is **not** installed during infrastructure setup. Sites are added through the management menu.\n\n## Management menu\n\n```bash\nsudo bash src/menu.sh\n```\n\nThe menu shows system resources and service status, then lists options by category:\n\n```\n  --- Sites ---\n  1)  Add New WordPress Site\n  2)  List All Sites\n  3)  Enable / Disable a Site\n  4)  Remove a Site\n  --- WordPress ---\n  5)  Update WordPress Core \u0026 Plugins\n  6)  Reset WordPress Admin Password\n  7)  Change PHP Version for a Site\n  --- Backup \u0026 Restore ---\n  8)  Backup a Site\n  9)  Restore a Site\n  10) Manage Backups (List / Delete)\n  --- System ---\n  11) Service Status Overview\n  12) Container Resource Usage\n  13) Disk Usage Per Site\n  14) Restart Services\n  15) View Logs\n  16) Renew All SSL Certificates\n  17) SSL Certificate Details\n  --- Settings ---\n  18) Update WP-Manager\n  19) Uninstall PHP Container\n  20) Toggle auto-show on SSH login\n  0)  Exit\n```\n\n### Adding a site\n\nSelect option **1** and provide:\n\n| Prompt | Example |\n|---|---|\n| Site label | `myshop` (used for DB/user/container names) |\n| Domain | `example.com` |\n| SSL | yes/no, optionally include `www.example.com` |\n| PHP version | `8.3` (default) |\n\nThe script will:\n\n1. Create a system user for the site\n2. Build a PHP-FPM Docker image (if not cached) and start a container on an available port\n3. Create an Nginx server block with security headers\n4. Create a dedicated MariaDB/MySQL database and user\n5. Download WordPress via WP-CLI and create `wp-config.php`\n6. Optionally obtain a Let's Encrypt SSL certificate\n7. Record everything in the SQLite state database\n\n\u003e [!TIP]\n\u003e The PHP image build takes 2-3 minutes the first time (compiling imagick and redis extensions). Subsequent site additions reuse the cached image and take around 10 seconds.\n\n### Enabling / Disabling a site\n\nSelect option **3** to take a site offline without deleting it. The Nginx config is renamed to `.conf.disabled` and Nginx reloads. All files, the database, and the PHP container remain untouched. Re-enabling reverses this instantly.\n\n### Updating WordPress\n\nSelect option **5** to run `core update`, `plugin update --all`, and `theme update --all` via WP-CLI inside the site's PHP container. Works on a single site or all sites at once.\n\n### Resetting the admin password\n\nSelect option **6** to list admin accounts for a site and set a new password via WP-CLI.\n\n### Changing PHP version\n\nSelect option **7** to stop a site's PHP container, pull the new PHP version image, and restart.\n\n### Backup and restore\n\n- **Option 8** — create a timestamped backup (files + database) for a site\n- **Option 9** — restore a site from any existing backup; file and database restores are selected independently\n- **Option 10** — list all backups with sizes, delete a single file, or wipe all backups for a domain\n\n### Container resource usage\n\nSelect option **12** for a `docker stats` snapshot showing CPU, memory, network I/O, and disk I/O for all PHP containers.\n\n### Disk usage per site\n\nSelect option **13** for a table of disk usage per site under `/var/www`, with the total at the bottom.\n\n### Updating WP-Manager\n\nSelect option **18** to check for upstream updates and pull the latest version. The current and remote commit hashes are shown before you confirm.\n\n### Uninstalling a PHP container\n\nSelect option **19** to remove a stopped or unused PHP-FPM container and optionally its image. Site files and the database are not affected.\n\n## CLI reference\n\nAll operations are available as standalone scripts:\n\n```bash\n# Infrastructure setup\nsudo bash src/install.sh\n\n# Add a site\nsudo bash src/add-site.sh example.com \\\n  --php-version 8.3 \\\n  --email admin@example.com \\\n  --ssl\n\n# Remove a site (auto-backup before removal)\nsudo bash src/remove-site.sh example.com\nsudo bash src/remove-site.sh example.com --force   # skip confirmation\n\n# Backup a site\nsudo bash src/backup.sh example.com\n\n# System status\nsudo bash src/status.sh           # human-readable\nsudo bash src/status.sh --json    # JSON output\n```\n\n## Managing multiple sites\n\nEach site gets isolated resources:\n\n| Resource | Detail |\n|---|---|\n| **PHP container** | `wp_php_\u003cdomain\u003e` |\n| **PHP port** | unique per site, starting at 9000 |\n| **Nginx config** | `/etc/nginx/conf.d/\u003cdomain\u003e.conf` |\n| **Database** | `\u003cprefix\u003e_db` with dedicated user |\n| **System user** | dedicated Unix user |\n| **Site files** | `/var/www/\u003cdomain\u003e/` |\n\nShared resources:\n\n| Resource | Detail |\n|---|---|\n| **MariaDB/MySQL** | `wp_db` container |\n| **Redis** | `wp_redis` container |\n| **Docker network** | `wp_network` |\n| **Certbot** | single install with auto-renewal timer |\n| **State database** | `state.db` (SQLite) |\n\n## Backups\n\nBackups can be created from the menu (option **8**) or via CLI:\n\n```bash\nsudo bash src/backup.sh example.com\n\n# Custom output directory\nsudo bash src/backup.sh example.com --output /mnt/backups\n```\n\nOutput files:\n\n```\nbackups/\n  example.com_files_2026-05-25_093000.tar.gz\n  example.com_db_2026-05-25_093000.sql\n```\n\nA backup is also created automatically when a site is removed.\n\n### Restoring a site\n\nUse menu option **9** to restore from any existing backup. File and database restores are independent, so you can roll back just the database after a bad plugin update without touching the files.\n\nUse menu option **10** to list backup sizes, delete individual files, or remove all backups for a domain.\n\n## State database\n\nAll site metadata is stored in `state.db` (SQLite):\n\n```bash\npython3 src/lib/state.py list                   # list all sites\npython3 src/lib/state.py list --json            # JSON output\npython3 src/lib/state.py get example.com        # single site as JSON\npython3 src/lib/state.py count                  # site count\npython3 src/lib/state.py config-list            # global config\n```\n\nStored fields: domain, site directory, PHP version, port, database name/user/password, system user, SSL status, WordPress install status, and timestamps.\n\n## File structure\n\n```\nwordpress-docker-fpm-nginx/\n├── install.sh                  # one-command VPS bootstrapper\n├── docker-compose.yml          # shared services (DB, Redis)\n├── nginx/\n│   ├── conf.d/\n│   │   └── wordpress.conf      # default Nginx server block\n│   ├── includes/\n│   │   └── wordpress-base.conf # shared Nginx includes (security headers, locations)\n│   └── nginx.conf              # global Nginx config\n├── php/\n│   ├── Dockerfile              # PHP image with imagick, redis, WP-CLI\n│   └── php.ini                 # PHP config overrides\n└── src/\n    ├── install.sh              # core infrastructure installer\n    ├── menu.sh                 # interactive management menu\n    ├── add-site.sh             # provision a new WordPress site\n    ├── remove-site.sh          # remove a site with rollback\n    ├── backup.sh               # file + database backup\n    ├── status.sh               # system health check (text or JSON)\n    └── lib/\n        ├── common.sh           # shared helpers (colors, logging)\n        ├── docker.sh           # Docker container management\n        ├── nginx.sh            # Nginx config generation\n        ├── state.py            # SQLite state database (Python CLI)\n        └── state.sh            # Bash wrappers for state.py\n```\n\n## Rollback safety\n\nBoth `add-site.sh` and `remove-site.sh` register undo operations before each destructive step. If any step fails, the rollback runs in reverse order and cleans up any created resources (users, containers, databases, configs).\n\n## Troubleshooting\n\n### PHP container fails to start\n\n```bash\ndocker logs wp_php_\u003cdomain\u003e\n\ndocker rm -f wp_php_\u003cdomain\u003e\nsudo bash src/add-site.sh \u003cdomain\u003e --php-version \u003cversion\u003e\n```\n\n### Nginx configuration error\n\n```bash\nnginx -t\nnginx -s reload\n```\n\n### SSL certificate renewal fails\n\n```bash\ncertbot renew --dry-run\ncertbot renew\n```\n\n### Docker network issues\n\n```bash\ndocker network ls\ndocker network inspect wordpress-docker-fpm-nginx_wp_network\n```\n\n### WordPress admin password\n\nUse menu option **6** to reset the admin password without needing to log in to WordPress.\n\n### Database credentials\n\nAll credentials are stored in the state database:\n\n```bash\npython3 src/lib/state.py get \u003cdomain\u003e\n```\n\n\u003e [!WARNING]\n\u003e The state database contains plaintext database passwords. Keep `state.db` secure and never commit it to version control.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fnooblk-98%2Fwordpress-docker-fpm-nginx","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fnooblk-98%2Fwordpress-docker-fpm-nginx","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fnooblk-98%2Fwordpress-docker-fpm-nginx/lists"}