Skip to content

Server Setup

This will be a living document to provide info about the common steps to set up a web server as of 2024. Hopefully it can provide some level of use to individuals, and hopefully over time I will be able to come back and make sure it is all working.

DNS, the most important foundational step

The roots of a good server configuration is DNS records that aren't fucked up.

Nameservers

Soon(TM)

A records

Soon(TM)

MX records

Soon(TM)

SRV (service) Records

Soon(TM)

SPF

(Sender Policy Framework)

  • Purpose: SPF helps prevent email impersonation by specifying which servers are allowed to send emails on their behalf.

  • Report: If an email fails SPF, it means the sender's claim about the email's origin is questionable.

Record Example

Type: TXT

Domain:

Coming Soon
Value:

Coming Soon
Notes: None at this time

DKIM

(DomainKeys Identified Mail)

  • Purpose: DKIM ensures the email you receive is unaltered and truly comes from the claimed sender by adding a digital signature.

  • Report: A DKIM failure report suggests that the email's digital signature doesn't match the one associated with the sender's domain.

Record Example

Type: TXT

Domain:

Coming Soon
Value:

Coming Soon
Notes: Must be custom generated per application and properly "assigned" almost akin to a public-private keypair.

DMARC

(Domain-based Message Authentication, Reporting, and Conformance)

  • Purpose: DMARC builds on SPF and DKIM to provide stronger email authentication and reporting. It helps prevent email impersonation.

  • Report: If you get a DMARC report, it means the sending domain is using DMARC and you're receiving feedback about the email authentication results to monitor authenticity and security.

Record Example

Type: TXT

Domain:

_dmarc.domain.com
Value:

v=DMARC1; p=none;
Notes:

For some reason, a lot of DMARC records are showing as fail, not sure why though... Will update this when I figure out what I am doing wrong.

Starting Out

First, you want to get the always free plan of Oracle Cloud. You can get a 8 core ARM server with 24gb of RAM and 200GB SSD space for literally completely free. You dont even need to add a payment method. It's awesome!

I also reccomend purchasing your domain names through Cloudflare. You're gonna use them as a CDN or NS either way, so why not let them own part of your soul?

The setup here is straight forward, the only thing to know is that you want to DISABLE encryption (it say between CPU, storage, and boot drive) because it tanks performance comparatively, and realistically, if you're reading this not as reference but as a step by step guide, you probably shouldn't be entrusting your cybersecurity in my hands, and you sure as shit shouldn't be trusting yourself to host sensitive, non-public data on a server. Leave that shit to the pros.

Note

Make sure you use ubuntu. Canonical is a moralistic and kind company, and they have the most documentation. Plus, the oracle image is based on arch, which is 🤮 but ubuntu is based on debian, which is 🥵

Finally, before you click 'gimme that sweet free server', make sure you actually name your instance something good. It shows up in the console, which means you have to stare at it all of the time.

Initial Configuration

First things first, set the fucking ubuntu password (or make a new account, I'm not gonna help you with that part if you choose to do so, because while using the ubuntu account is a danger if you decide you want to allow password login, you should be using a keypair instead, so password login is disabled meaning you dont have to worry about it.)

To do this, run the following command

passwd

The reason you do this is so if you ever break your install (like I have many times) by, for example, changing the perms on the .ssh folder, or messing with the SFTP config and blocking SSH connections, you can now use the password you set in the cloud console on the web inside Oracle Cloud so that you dont have to delete and start over. Yay!

Next, since this part is just kinda an annoyance and you'll forget later, you want to set up your hosts file to work with all of the different sites you want to use. Type

sudo nano /etc/hosts

Note

If, for whatever reason, nano isn't installed

sudo apt install nano

Now once you are in there, you should see a line that has 127.0.1.1 or ..0.1, simply add all of your FQDNs right after like so

127.0.1.1 thenathe.me www.thenathe.me arizona.computer www.arizona.computer

Now you wont forget this step later.

Install Apache

Now, install apache with

sudo apt install apache2
and certbot with
sudo apt install certbot python3-certbot-apache
Once that is all done, you need to make a new site, so do
sudo nano /etc/apache2/sites-available/your_domain.conf
and make sure to set up the following

sudo chmod -R 755 /var/www

Virtual Host Config

<VirtualHost 0.0.0.0:80> 
#important to change this from * to 0.0.0.0
    ServerAdmin [email protected] 
    #should probably make this a real email

    ServerName thenathe.me 
    #actual server name, dont do www unless you actually want www to be the main domain. otherwise you will set up www redir later

    DocumentRoot /var/www/thenathe.me/ 
    #if you are using mkdocs, add /site/ to the end

    ErrorLog ${APACHE_LOG_DIR}/example.com_error.log
    CustomLog ${APACHE_LOG_DIR}/example.com_access.log combined

    RewriteEngine on
    RewriteCond %{SERVER_NAME} =thenathe.me 
    #remember to change your name here too

    RewriteRule ^ https://%{SERVER_NAME}%{REQUEST_URI} [END,NE,R=permanent]
</VirtualHost>

then make sure that you copy that for each additional site. Use

sudo cp /etc/apache2/sites-available/your_domain.conf /etc/apache2/sites-available/your_domain2.conf 

Finally,

a2ensite yourdomain.com 
for each

sudo systemctl reload apache2

Note

If you ever make additional hosts, perform the above steps again, and also make sure to take set permissions and take ownership of the folders you make in /var/www

sudo mkdir /var/www/newsite.com
Then make the new config using cp

sudo chmod -R 755 /var/www/newsite.com
sudo chown -R ubuntu:www-data /var/www/newsite.com

If you want to make a symlink to your home directory to make development on VSCode easier (or ftp or whatever)

ln -s /var/www/site.com ~/site.com

If you set the ownership above to ubuntu:www-data, it should work to allow you and your site to both edit the files. I don't really understand/know how or why this works, but it does.

IPTables/Firewall

Now let's allow the stuff through the firewall:

sudo apt install iptables-persistent

sudo iptables -A INPUT -i lo -j ACCEPT
sudo iptables -A OUTPUT -o lo -j ACCEPT

sudo iptables -A INPUT -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT
sudo iptables -A OUTPUT -m conntrack --ctstate ESTABLISHED -j ACCEPT

sudo iptables -A INPUT -m conntrack --ctstate INVALID -j DROP

sudo iptables -A INPUT -p tcp --dport 22 -m conntrack --ctstate NEW,ESTABLISHED -j ACCEPT
sudo iptables -A OUTPUT -p tcp --sport 22 -m conntrack --ctstate ESTABLISHED -j ACCEPT

sudo iptables -A INPUT -p tcp -m multiport --dports 80,443 -m conntrack --ctstate NEW,ESTABLISHED -j ACCEPT
sudo iptables -A OUTPUT -p tcp -m multiport --dports 80,443 -m conntrack --ctstate ESTABLISHED -j ACCEPT

sudo iptables -A INPUT -p tcp -m multiport --dports 80,443 -m conntrack --ctstate NEW,ESTABLISHED -j ACCEPT
sudo iptables -A OUTPUT -p tcp -m multiport --dports 80,443 -m conntrack --ctstate ESTABLISHED -j ACCEPT

sudo iptables -A INPUT -p tcp --dport 25565,19132,19133 -j ACCEPT #bonus, minecraft
sudo iptables -A INPUT -p udp --dport 25565,19132,19133 -j ACCEPT

sudo netfilter-persistent save

This will allow loopback (internal connections), established connections, SSL, HTTP, HTTPS, and optionally, minecraft. Too bad Oracle Cloud has issues with ufw sigh

Note

A lot of these are probably unnecessary, but I can't remember what I did the last time I had to troubleshoot it. Every time I always missed the hosts file step, so I am not even 100% sure that ufw doesnt work. I will update this guide once I figure that out! 😬

Now you want to set up these same rules inside Oracle Cloud web console yourself. Go to subnet settings, then make new firewall rules.

SSL using Certbot

Now you wanna use certbot. Make sure all of your DNS is pointed to the right spot with A records, and verify that you can either connect to the domain name OR get a redirect loop (if on Cloudflare)

Warning

If you get a redirect loop, on Cloudflare, set SSL/TLS to Full (Strict). That's how it should be in the first place, but Cloudflare does stuff fucky sometimes... 🤷

Now,

sudo certbot --apache

Follow the prompts, and you're done!

Install PHP

Warning

PHP might already be set up, check first or you run the risk of breaking something. To test, make a .php file inside of the www folder and then add the following contents

phpinfo();

sudo apt install php libapache2-mod-php php-cli php-cgi php-mysql 
If you want PostgreSQL instead, though I don't recommend it
sudo apt install php libapache2-mod-php php-cli php-cgi php-pgsql

Configure Variables and minor setup

TDB

Extra Step: HTML as PHP

If you're using mkdocs like me, you want to be able to handle php code on your server so that you can potentially do stuff like secure authentication, comment systems, etc. To do this, add the following lines to your /etc/apache2/apache2.conf

<IfModule mime_module>
    # Change the mime type of .html file to php
    AddType application/x-httpd-php .html

    # Set handler for .html files to php-script
    <FilesMatch \.html$>
        SetHandler application/x-httpd-php
    </FilesMatch>
</IfModule>

Please note, there is apparently a performance degradation with this, but I haven't noticed besides literally the first pageload.

If you can read this, this trick is still working...

Install MySQL

MariaDB

The only MySQL implementation you should use

sudo apt install mariadb-server

sudo systemctl start mariadb.service

Warning

MySQL has a secure installation feature, but it's fucked. Before you run the next part, make sure to set the mysql password. If you set up the server correctly, meaning that there is no outside access without public private key pairing, making this password the same as the serial recovery password is probably a decent idea.

sudo mysql
ALTER USER 'root'@'localhost' IDENTIFIED WITH mysql_native_password BY 'password';

exit
Check the password
mysql -u root -p
Once that is done, continue...

sudo mysql_secure_installation

If you want to make a dedicated user to maybe stop brute force attempts:

mysql -u root -p
CREATE USER 'username'@'host' IDENTIFIED WITH mysql_native_password BY 'password';
We use mysql_native_password because phpmyadmin is sometimes fussy without it

Then, for each table, run the following command:

GRANT PRIVILEGE ON database.table TO 'username'@'host';
and you can replace database or table with * so it would be like

GRANT PRIVILEGE ON database.* TO 'username'@'host';
to give the user perms for the whole database. Finally

GRANT CREATE, ALTER, DROP, INSERT, UPDATE, INDEX, DELETE, SELECT, REFERENCES, RELOAD on *.* TO 'username'@'localhost' WITH GRANT OPTION;

or, if you are feeling lucky (and made a wacky username so people cant guess it, and take regular backups) you can instead

GRANT ALL PRIVILEGES ON *.* TO 'username'@'localhost' WITH GRANT OPTION;
to make it a 'root' user but with a hard to guess name.

Finally,

FLUSH PRIVILEGES;

exit
sudo mysqladmin -p -u username version
to test

PHPMyAdmin

sudo apt install phpmyadmin php-mbstring php-zip php-gd php-json php-curl

sudo ln -s /etc/phpmyadmin/apache.conf /etc/apache2/conf-available/phpmyadmin.conf
sudo a2enconf phpmyadmin.conf
sudo systemctl reload apache2.service

Optional Step: Minecraft?!

Minecraft on ARM is pretty easy

apt-cache search openjdk
To find the most newest-er version of openJDK, then once you got that

sudo apt-get install openjdk-17-jdk #or whatever the number is

java -version

Once you got that, simply download the server jar and run it with the commandline!

Configure the Firewall

See above

Fixing SFTP sites

Allow the ubuntu user to sftp into /var/www for use with FTP clients and VSCode remote file editing

sudo adduser ubuntu www-data
sudo chown -R www-data:www-data /var/www
sudo chmod -R g+rwX /var/www

Redirect Loop

Set CloudFlare SSL/TLS > Overview > security to Full to stop redirect loop from selfsigned SSL certs.

Content, and why you should choose something with markdown

First, I wanted to use MDWiki, which is really great except for the fact that it has been abandoned for like 11 years which is kinda wild to think about considering it still "works". The reason I moved off of it was because it was slow as shit on mobile, taking upwards of 35 seconds to load. I was told it was because of "script evaluation", but the JS files are actually quite small (smaller than this site, which loads instantly, so there was clearly a problem). Read the next part for more on this.

I settled on mkdocs because it is essentially the same thing but a little worse. It requires you to actually install a program 🤮 and then build the site with a command after each change to the documents 🤮 🤮 🤮 but at least it is quick as hell. Probably because it actually generates html from markdown rather than rendering it realtime, I would assume. Anyway, the cinder theme, with some tweaking of css (which you can find in your f12 sources tab if you are so interested) is what you see here, which is essentially MDWiki but modern.

Why I hate installed web programs, and why you should too

When I was trying to fix MDWiki's mobile slowness, I figured "oh, I should recompile from the source code. How hard could it be?" Very, very hard, it turns out! I ran into all these errors, needed to install like 20 programs, needed to configure the path, etc. Then, hearing the words of vapid developers echoing in my head, I decided to spin up WSL and try the build on Linux. It still didn't work.

Frankly, what the FUCK happened to just editing a JS file and calling it a day? Why do we need installed dependencies like node.js and random bullshit that forces out development environment to exist outside of XAMPP and a good ol' text editor? Am I wrong? No, it is the kids who are wrong!

VSCode, the real CMS

I was an adamant Notepad++ user for years, and while it is still great (see my video here), there is increasingly little reason to use it over Visual Studio Code. One of the main reasons is relevant to this guide: remote editing. Since you set up the SFTP access so the ubuntu user can access the website directories, you can now use VSCode to connect remotely and edit, upload, and create new files directly on the server. It's essentially a CMS, but without all of the bulky overhead of something like wordpress, allowing you to easily log in and create new files on the go. I havent fucked around with a mobile solution to this yet, but frankly I can just jot my thoughts down and upload them when I get home.

To use VSCode like this, get the Microsoft offical Remote SSH plugins -- there are two of them -- and then just set up everything with your public private key.

Note

When you connect the first time, you will fail. That's okay! Go into your VSCode config settings and make sure that the whole path is written out under the ssh key file -- C:\Users\Username.ssh\id_rsa

Finally, the other reason I chose VSCode is because it is very convenient to type mkdocs build after you do any editing because the terminal is at the bottom of the screen. It really is a very good IDE, and I am personally offended that I slept on it as long as I did.

Closing Thoughts

Please hit me up on discord if you notice something is wrong! This document is everchanging as things work or cease to, so please check back often!