This is the thing that you google fiercely during one or two hours and find the solution.
Hopefully this guide might help you to do that in half hour, ;-)
sudo dnf install nginx
)sudo dnf install python3-certbot-nginx
certbot --nginx --redirect -d mydomain.cc -d sub1.mydomain.cc -d sub2.mydomain.cc -m your@email.com --agree-tos
)sudo setsebool -P httpd_can_network_connect 1
Most services that sells domains also tries to sell you hosting, email, online shops, things like that.
Other providers like aws, digital ocean, gcp, oci, ibm cloud, red hat and others offer a wider range of products to use along those domain names.
The drill is the same on almost every case:
And yes, you can create as many subdomains you wish!
To our example let's pretend we bought mydomain.cc
and we'll use two
subdomains: sub1.mydomain.cc
and sub2.mydomain.cc
.
Just install fedora 37, create a user and make him a sudoer:
adduser myuser
usermod -a -G wheel myuser
# don't forget to create a password for this guy!
passwd myuser
Use that user for now on.
Most cloud providers has some sort of console available to access newly created machines, others ask you for an ssh key, and you get root access when using it.
Now the fun starts.
sudo dnf install nginx
sudo dnf install python3-certbot-nginx # more details later
It gives you a shiny new nginx acting as a server with a config at
/etc/nginx/nginx.conf
which looks like this (comments removed for readability:
worker_processes 1;
events {
worker_connections 1024;
}
http {
include mime.types;
default_type application/octet-stream;
sendfile on;
keepalive_timeout 65;
server {
listen 80;
server_name localhost;
location / {
root html;
index index.html index.htm;
}
error_page 500 502 503 504 /50x.html;
location = /50x.html {
root html;
}
}
}
You need to add your reverse proxy configuration on that file.
Nginx allows much cleaner configurations using /etc/nginx/conf.d
and
/etc/nginx/default.d
directories, but the certbot plugin will fail if it
doesn't find the reverse proxy configurations for your domains and subdomains.
So you'll need to do something like this (again comments removed):
worker_processes 1;
events {
worker_connections 1024;
}
http {
include mime.types;
default_type application/octet-stream;
sendfile on;
keepalive_timeout 65;
server {
listen 80;
server_name localhost;
location / {
root html;
index index.html index.htm;
}
error_page 500 502 503 504 /50x.html;
location = /50x.html {
root html;
}
}
server {
listen 80;
server_name mydomain.cc;
location / {
proxy_pass http://127.0.0.1:3000;
proxy_http_version 1.1;
proxy_buffering off;
gzip off;
}
}
server {
listen 80;
server_name sub1.mydomain.cc;
location / {
proxy_pass http://127.0.0.1:8080;
proxy_http_version 1.1;
proxy_buffering off;
gzip off;
}
}
server {
listen 80;
server_name sub2.mydomain.cc;
location / {
proxy_pass http://127.0.0.1:9090;
proxy_http_version 1.1;
proxy_buffering off;
gzip off;
}
}
}
In this configuration, nginx will proxy external requests from your domains and subdomains to some internal services.
Now we're good to call certbot. register your domains:
sudo certbot --nginx --redirect -d mydomain.cc -d sub1.mydomain.cc -d sub2.mydomain.cc -m my@email.com --agree-tos
That should be enough.
If you hit some error, try to install the certs one by one:
sudo certbot install -v --cert-name mydomain.cc
sudo certbot install -v --cert-name sub1.mydomain.cc
sudo certbot install -v --cert-name sub2.mydomain.cc
If you are unsure if you have any certs at all, see them with this command:
sudo certbot certificates
After installing the certs, the nginx.conf file will look like this:
worker_processes 1;
events {
worker_connections 1024;
}
http {
include mime.types;
default_type application/octet-stream;
sendfile on;
keepalive_timeout 65;
server {
listen 80;
server_name localhost;
location / {
root html;
index index.html index.htm;
}
error_page 500 502 503 504 /50x.html;
location = /50x.html {
root html;
}
}
server {
listen 80;
server_name mydomain.cc;
location / {
proxy_pass http://127.0.0.1:3000;
proxy_set_header Host $host;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_http_version 1.1;
proxy_buffering off;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
gzip off;
}
listen 443 ssl; # managed by Certbot
ssl_certificate /etc/letsencrypt/live/mydomain.cc/fullchain.pem; # managed by Certbot
ssl_certificate_key /etc/letsencrypt/live/mydomain.cc/privkey.pem; # managed by Certbot
include /etc/letsencrypt/options-ssl-nginx.conf; # managed by Certbot
ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem; # managed by Certbot
}
server {
listen 80;
server_name sub1.mydomain.cc;
location / {
proxy_pass http://127.0.0.1:8080;
proxy_set_header Host $host;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_http_version 1.1;
proxy_buffering off;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
gzip off;
}
listen 443 ssl; # managed by Certbot
ssl_certificate /etc/letsencrypt/live/sub1.mydomain.cc/fullchain.pem; # managed by Certbot
ssl_certificate_key /etc/letsencrypt/live/sub1.mydomain.cc/privkey.pem; # managed by Certbot
include /etc/letsencrypt/options-ssl-nginx.conf; # managed by Certbot
ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem; # managed by Certbot
}
server {
listen 80;
server_name sub2.mydomain.cc;
location / {
proxy_pass http://127.0.0.1:9090;
proxy_set_header Host $host;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_http_version 1.1;
proxy_buffering off;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
gzip off;
}
listen 443 ssl; # managed by Certbot
ssl_certificate /etc/letsencrypt/live/sub2.mydomain.cc/fullchain.pem; # managed by Certbot
ssl_certificate_key /etc/letsencrypt/live/sub2.mydomain.cc/privkey.pem; # managed by Certbot
include /etc/letsencrypt/options-ssl-nginx.conf; # managed by Certbot
ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem; # managed by Certbot
}
server {
if ($host = mydomain.cc) {
return 301 https://$host$request_uri;
} # managed by Certbot
listen 80;
server_name mydomain.cc;
return 404; # managed by Certbot
}
server {
if ($host = sub1.mydomain.cc) {
return 301 https://$host$request_uri;
} # managed by Certbot
listen 80;
server_name sub1.mydomain.cc;
return 404; # managed by Certbot
}
server {
if ($host = sub2.mydomain.cc) {
return 301 https://$host$request_uri;
} # managed by Certbot
listen 80;
server_name sub2.mydomain.cc;
return 404; # managed by Certbot
}
}
That should be fine to restart your nginx service:
sudo systemctl restart nginx.service
Cockpit is a tool to remotely manage your server and is very honest and good enough for day-to-day tasks.
You can install it this way:
sudo dnf install cockpit cockpit-system cockpit-storaged cockpit-podman cockpit-packagekit
In order to make cockpit behave with nginx, add this config into
/etc/cockpit/cockpit.conf
:
[WebService]
Origins = https://sub2.mydomain.cc wss://sub2.mydomain.cc http://127.0.0.1:9090 ws://127.0.0.1:9090
ProtocolHeader = X-Forwarded-Proto
AllowUnencrypted = true
[Log]
Fatal = /var/log/cockpit.log
[Session]
IdleTimeout = 15
Now enable it:
sudo systemctl enable --now cockpit.socket
You might run into permission denied issues thanks to selinux:
2023/04/06 19:01:14 [crit] 4973#4973: *1 connect() to 127.0.0.1:9090 failed (13: Permission denied) while connecting to upstream, client: xxx.xx.xxx.xx, server: sub2.mydomain.cc, request: "GET /favicon.ico HTTP/1.1", upstream: "http://127.0.0.1:9090/favicon.ico", host: "sub2.mydomain.cc", referrer: "http://sub2.mydomain.cc/"
In order to resolve that, simply hit this command:
sudo setsebool -P httpd_can_network_connect 1
Now cockpit is supposed to attend on https://sub2.mydomain.cc
, you can spin up
a firewall and close everything but 80 and 443 now. All you need is cockpit.
It's still nice to see that foundation ops technologies still viable and working with little to zero vendor lock-in.
Modern cloud providers gives us more and more nice toys which on one hand makes us totally forget about tooling and infrastructure, like Digital ocean apps, Google App Engine, Amazon Lightsail, Heroku, IBM Code Engine and so on, but in contrast makes our lives harder if we need to switch clouds or build some resiliency across several providers.
This guide might or might not work on other linux distros.
Happy hacking!