Skip to content
Bullionet
Getting started

Installing applications

A web server with HTTPS, a database, Docker, a control panel. The commands that cover most of what a dedicated server is asked to run.

Your server arrives with the system you picked and nothing on top. This page covers what gets installed on it most often, with commands for Debian and Ubuntu first, and the Rocky and AlmaLinux equivalent where it differs.

Everything below assumes you are connected over SSH and that you have done the hardening pass, the firewall in particular: a service you install is reachable from the whole internet the second it starts.

Always start here ​

bash
apt update && apt full-upgrade     # Debian, Ubuntu
dnf upgrade --refresh              # Rocky, AlmaLinux

A web server ​

Nginx serves static files and stands in front of everything else:

bash
apt install nginx                  # Debian, Ubuntu
dnf install nginx                  # Rocky, AlmaLinux
systemctl enable --now nginx
ufw allow 'Nginx Full'             # or: firewall-cmd --permanent --add-service={http,https} && firewall-cmd --reload

Your server now answers on http://<your-ip> with the default page. Files are served from /var/www/html, and site configurations live in /etc/nginx/sites-available on Debian and Ubuntu, /etc/nginx/conf.d elsewhere.

Apache is the other classic and works just as well: replace nginx with apache2 (Debian, Ubuntu) or httpd (Rocky, AlmaLinux).

HTTPS, free, in two minutes ​

Point your domain at the server's IP address first: an A record on example.com holding the address. Then:

bash
apt install certbot python3-certbot-nginx
certbot --nginx -d example.com -d www.example.com

Certbot asks for an email address, edits the nginx configuration and reloads it. Renewal is automatic, twice a day, through a timer it installs itself.

Careful

The certificate is issued only if the domain already resolves to this server. A DNS record changed five minutes earlier may not have propagated yet: wait, then run the command again.

A database ​

MariaDB, the drop-in MySQL:

bash
apt install mariadb-server
systemctl enable --now mariadb
mariadb-secure-installation        # set a root password, answer yes to the rest
bash
mariadb -e "CREATE DATABASE myapp CHARACTER SET utf8mb4;"
mariadb -e "CREATE USER 'myapp'@'localhost' IDENTIFIED BY 'a-long-password';"
mariadb -e "GRANT ALL ON myapp.* TO 'myapp'@'localhost';"

PostgreSQL, if your application asks for it:

bash
apt install postgresql
sudo -u postgres createuser --pwprompt myapp
sudo -u postgres createdb --owner=myapp myapp

Good to know

Leave the database listening on localhost unless something outside the machine genuinely needs it. A database open to the internet is found by scanners within hours.

PHP and WordPress ​

bash
apt install php-fpm php-mysql php-curl php-gd php-mbstring php-xml php-zip

Then point a site at the PHP socket, drop WordPress in /var/www/html, and create its database as above. WordPress asks for the database name, the user and the password in its installer.

bash
cd /var/www/html
curl -O https://wordpress.org/latest.tar.gz
tar xzf latest.tar.gz --strip-components=1 && rm latest.tar.gz
chown -R www-data:www-data /var/www/html      # nginx:nginx on Rocky and AlmaLinux

Docker ​

For anything shipped as a container:

bash
curl -fsSL https://get.docker.com | sh
systemctl enable --now docker
docker run --rm hello-world

docker compose comes with it. A compose.yaml in a folder, then docker compose up -d, and your stack runs.

Careful

Docker writes its own firewall rules and can publish a port that ufw believes is closed. Publish on the loopback interface (-p 127.0.0.1:8080:80) for anything that should stay behind your reverse proxy.

A Node.js application ​

bash
curl -fsSL https://deb.nodesource.com/setup_22.x | bash -
apt install nodejs
npm install -g pm2
pm2 start app.js && pm2 startup && pm2 save

Then have nginx forward to it, so the application never faces the internet directly and inherits your certificate:

nginx
location / {
    proxy_pass http://127.0.0.1:3000;
    proxy_set_header Host $host;
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    proxy_set_header X-Forwarded-Proto $scheme;
}

A control panel ​

If you would rather click than type, a hosting panel installs the whole stack and manages sites, mailboxes and certificates for you:

  • Webmin is free and installs on an existing system.
  • Plesk, cPanel and DirectAdmin are licensed products, so they need a licence you buy from the publisher or through us.
  • CyberPanel and CloudPanel are free and aimed at web hosting.

All of them expect a freshly installed machine and take it over. Install the panel first, everything else through it. If the server is already in production, reinstall it rather than layering a panel on top.

Check what is listening ​

After any install, look at what you have just exposed:

bash
ss -tulpn | grep LISTEN

Every line with 0.0.0.0 or [::] is reachable from the internet. If that was not the intention, bind the service to 127.0.0.1 or close the port.

Backups are yours ​

Nothing on the machine is backed up on our side, and a reinstall wipes the drives. Copy what matters elsewhere, on a schedule, and test the restore at least once.

bash
# database dump, kept for a week
mariadb-dump --all-databases | gzip > /root/backup-$(date +%F).sql.gz
find /root -name 'backup-*.sql.gz' -mtime +7 -delete

Reviewed on September 14, 2026