LEMP server with Let's Encrypt SSL via NGINX Proxy Manager

In this guide, we'll deploy a LEMP server using the pre-built webdevops/php-nginx:8.4 , which already includes the necessary PHP extensions and a web server. We'll also enable free SSL from Let's Encrypt via the NGINX Proxy Manager.

What you will need

Project structure

Create a project structure:

mkdir ~/lemp-docker && cd ~/lemp-docker mkdir www config Code language:  Bash  ( bash )

Create a config/php.ini (optional):

memory_limit = 256M upload_max_filesize = 64M post_max_size = 64M display_errors = On Code language:  Bash  ( bash )

Create a docker-compose.yml with the following contents:

services:
   app:
     image:  webdevops/php-nginx:8.2
     container_name:  lemp-app
     restart:  always
     ports:
       -  "8081:80"
     volumes:
       -  ./www:/app
       -  ./config/php.ini:/opt/docker/etc/php/php.ini
     environment:
       -  WEB_DOCUMENT_ROOT=/app
       -  PHP_DISPLAY_ERRORS=1
     networks:
       -  lemp-net

   db:
     image:  mariadb:10.5
     container_name:  lemp-db
     restart:  always
     environment:
       MYSQL_ROOT_PASSWORD:  rootpass
       MYSQL_DATABASE:  mydb
       MYSQL_USER:  myuser
       MYSQL_PASSWORD:  mypass
     volumes:
       -  db_data:/var/lib/mysql
     networks:
       -  lemp-net

   phpmyadmin:
     image:  phpmyadmin/phpmyadmin
     container_name:  lemp-pma
     expose:
       -  "80"
     environment:
       PMA_HOST:  lemp-db
       MYSQL_ROOT_PASSWORD:  rootpass
     networks:
       -  lemp-net

   npm:
     image:  jc21/nginx-proxy-manager:latest
     container_name:  nginx-proxy-manager
     restart:  always
     ports:
       -  "80:80"
       -  "443:443"
       -  "81:81"
     volumes:
       -  npm_data:/data
       -  npm_letsencrypt:/etc/letsencrypt
     networks:
       -  lemp-net

 volumes:
   db_data:
   npm_data:
   npm_letsencrypt:

 networks:
   lemp-net:
     driver:  bridge Code language:  YAML  ( yaml )

The MYSQL_ROOT_PASSWORD , MYSQL_DATABASE , MYSQL_USER and MYSQL_PASSWORD variables can be customized to suit your needs. These parameters are used for initial database initialization. If you want to store them separately, create a .env ${MYSQL_PASSWORD} syntax within docker-compose.yml .

Launching containers

Run containers with the command:

docker compose up -d Code language:  Bash  ( bash )

Go to the NGINX Proxy Manager control panel at http://SERVER_IP:81 .

Default authorization:

  • Login: admin@example.com
  • Password: changeme

Domain and SSL setup

Add a new Proxy Host in the NPM interface:

  • Domain: example.com
  • Forward Hostname/IP: lemp-app
  • Forward Port: 80
  • Enable SSL → Request a new certificate
  • Force SSL → Enable

Once saved, the site will be accessible at https://example.com with an automatically issued Let's Encrypt certificate.

Accessing phpMyAdmin

To configure access to phpMyAdmin, add a separate Proxy Host:

  • Domain: db.example.com
  • Forward Hostname/IP: lemp-pma
  • Forward Port: 80
  • Enable SSL → Request a new certificate
  • Force SSL → Enable

After that, open https://db.example.com and log in with the username myuser and password mypass , or use root .

CMS installation

You can upload the installation files for your CMS (for example, WordPress) to the www . Open https://example.com to begin the installation.

To connect to the database, use the following parameters:

  • Host: lemp-db
  • Database name: mydb
  • User: myuser
  • Password: mypass

Delete the previously created index.php with phpinfo(), if it is still present, so as not to interfere with the installation.

Stop and delete

Stopping all containers:

docker compose down Code language:  Bash  ( bash )

Deleting with volumes:

docker compose down -v Code language:  Bash  ( bash )

Our support team can handle all of the above when you order a cloud server (VPS) from Unihost.kz. We'll help you deploy the environment, configure Docker, and enable SSL.