Introduction
When working on multiplayer projects hosting a server is a key part of being able to share it with others.
In this article we will cover how to host a Godot (4.5.1) Server on an Oracle cloud instance. For this we will cover:
- The Godot project
- Dockerising a Godot server
- Hosting a Godot server to an Oracle instance
- Setting up HTTPS with NGINX and letsencrypt
- Hosting your client on itch.io
Requirements
- Godot 4.5.1
- Docker and a Docker account
- An Oracle cloud account
- Oracle has websites for each region so pick your closest
- An itch.io account
- A registered domain
- This is only required if you want HTTPS
- Personally I use GoDaddy
1. The Godot Project
The Godot project that we will host is using Godot 4.5.1 in compatibility mode and Godot's high-level multiplayer, specifically the WebSocketServer. This is because in this tutorial we will be hosting our client on the web.
As for what the project does, it allows players to join and leave a 2D space where they can move around with their connection ids shown above them.
You can find the source code for the project here.
2. Dockerising a Godot server
When dockerising an application it is important to have a clear idea of the steps we would manually take to achieve the same effect. In our case we want to have to have a Linux based version of our game running as a Server.
We can achieve this in the following steps:
-
Setup a Linux based system to run our Server
FROM ubuntu:focal AS build # Install dependenices to download Godot and templates RUN apt-get update && apt-get install -y --no-install-recommends \ ca-certificates \ unzip \ wgetFor this we are using the smallest ubuntu docker image I could find and then install dependencies to download Godot.
(If you know of a smaller one, let me know in the comments) -
Install Godot and the templates required to export projects for Linux
ENV GODOT_VERSION="4.5.1" # Download Godot and templates RUN wget https://github.com/godotengine/godot/releases/download/${GODOT_VERSION}-stable/Godot_v${GODOT_VERSION}-stable_linux.x86_64.zip RUN wget https://github.com/godotengine/godot/releases/download/${GODOT_VERSION}-stable/Godot_v${GODOT_VERSION}-stable_export_templates.tpz # Place Godot files in required folders RUN mkdir -p ~/.cache ~/.config/godot ~/.local/share/godot/export_templates/${GODOT_VERSION}.stable \ && unzip Godot_v${GODOT_VERSION}-stable_linux*.zip \ && mv Godot_v${GODOT_VERSION}-stable_linux*64 /usr/local/bin/godot \ && unzip Godot_v${GODOT_VERSION}-stable_export_templates.tpz \ && mv templates/* ~/.local/share/godot/export_templates/${GODOT_VERSION}.stable \ && rm Godot_v${GODOT_VERSION}-stable_export_templates.tpz Godot_v${GODOT_VERSION}-stable_linux*.zipHere we use
wgetto download Godot and the templates for exports from the Godot Github releases. -
Export a version of our game for Linux
# Create a space to build the executable RUN mkdir /godotbuildspace WORKDIR /godotbuildspace # Copy our Godot project into the container COPY . . ARG EXECUTABLE_NAME ENV EXPORT_NAME="LinuxServer" ENV EXECUTABLE_NAME=$EXECUTABLE_NAME # Export the project in debug or release mode ENV EXPORT_MODE="debug" RUN godot --export-${EXPORT_MODE} ${EXPORT_NAME} ${EXECUTABLE_NAME} --headlessWith Godot downloaded we can now export the project where:
-
EXECUTABLE_NAME: is the name of our final executable -
EXPORT_NAME: is the name of our Linux export in ourexport_presets.cfg -
EXPORT_MODE: is the type of export release or debug. I recommend at this stage usingdebugas this will allow you to see logs fromprint()in your Godot code.
This stage also requires you have setup a Linux export in your
export_presets.cfgfile. The easiest way to do this is in your Godot editor go toProject -> Exportand thenAdd... -> Linux.For this export preset we are using
Options -> Embed PCK = trueandResources -> Export Mode = Export as dedicated server. -
-
Run the exported version as a Server
# Start a new stage to execute the exectuable as we do not need the Godot files anymore FROM ubuntu:focal ARG EXECUTABLE_NAME ENV EXECUTABLE_NAME=$EXECUTABLE_NAME COPY --from=build /godotbuildspace/ ./ EXPOSE 6069/tcp EXPOSE 6069/udp CMD ["sh", "-c", "./${EXECUTABLE_NAME} --headless -s"]Finally we run the created executable. For this tutorial:
- Port
6069is used, as it is defined as the port the client will connect to here, and will require tcp and udp connections. - We run with the flag
--headlessas this runs Godot without visual elements, which the server will not require. - We run with the flag
-sas this is how in this project we tell our Godot project to run as a server not a client, the code of this can be seen here.
- Port
Now with this file we can build the container with docker build -t mutliplayer-hosting-tutorial-server . and run it with docker run -d -p 6069:6069 -p 6069:6069/udp mutliplayer-hosting-tutorial-server. However, if you do want to use this for local development I recommend using docker-compose.
For later steps we will need to push the image to our docker account so we can pull it on the Oracle instance.
docker build -t <Your Docker Username>/mutliplayer-hosting-tutorial-server .
docker push <Your Docker Username>/mutliplayer-hosting-tutorial-server
You can find the full Dockerfile here.
3. Hosting a Godot server to an Oracle instance
We are going to use Oracle for hosting our server as you can get two instances for free.
-
Create the Oracle Instance
Start by going to the instances section in Oracle Cloud and create a new instance.
For this we are using
Canonical Ubuntu 20.04image andVM.Standard.E2.1.Microshape.

Make sure to download your private and public key for SSH.
You can leave all the other settings as default.
-
Setup Port Connections
Our server will be communicating on port 6069 on both tcp and udp, so we need to allow connections on those ports.
For this we need to change our subnet rules to allow this traffic. These subnet rules can be changed for your instance by:
- Selecting your instance
- Going to the networking tab and selecting the subnet
- Then add a new one:
-
Download docker and run container
To connect to our server for our local machine we will use the ssh key we downloaded earlier. This can be done with the following command in your terminal:
ssh -i <Path to your .key file> ubuntu@<Public IP of your instance>Now on the machine we need to first update the package installer
aptand then install docker.
sudo apt update sudo apt install docker.ioThen download your published image and run it.
sudo docker pull <Your Docker username>/mutliplayer-hosting-tutorial-server sudo docker run -d -p 6069:6069 -p 6069:6069/udp <Your Docker username>/mutliplayer-hosting-tutorial-serverNow we can connect from our local client by updating
127.0.0.1to the public IP address of your server here.
4. Setting up HTTPS with NGINX and letsencrypt
We want to setup HTTPS as the current HTTP setup will work for local development builds of your Godot client if we want to host our client on itch.io we will require a secure connection to communicate with our server.
Currently we are using a websocket connection with ws:// and we will need to use a secure websocket connection with wss:// from a trusted domain meaning we cannot self sign the connection.
To get that secured signed connection we will be using letsencrypt which requires a registered domain to sign our connection as secure.
-
Security list updates
With the HTTPS setup we will not be using connection on a the port 6069 directly but instead traffic from the standard HTTPS port 443 will be forwarded to it. This means we can update our security list for the subnet removing 6069 and adding 80 and 443:
-
Point your domain to IP of server
For this tutorial we will be getting our domain from GoDaddy, you can pick up a cheap domain for year for cheap if you do not mind what the name of that domain will be.
With a domain we need to now setup a A Record, this points our domain to the Public IP address of our server.
This record will point traffic for the sub-domain
multiplayer-tutorialfor the domain to the public IP address of the server, such thatmultiplayer-tutorial.<Domain name>will go to the servers public IP address. -
Add a NGINX to server
Now we have our domain setup we need to handle requests coming to that domain and make sure any HTTP connections get redirection to HTTPS.
sudo apt install nginx # Verify that nginx is now running sudo service nginx statusNow we want to update our nginx config to send any traffic at the domain we defined to our Godot server. You can find the nginx config file at
/etc/nginx/nginx.conf, in this tutorial we will just directly edit this file.
# Open the config sudo nano /etc/nginx/nginx.confWe will then add the following
serverblock to thehttpblock:
http { server { server_name <Your subdomain>.<Your domain>; location / { # redirect all HTTP traffic to localhost:6069 proxy_pass http://localhost:6069; proxy_set_header X-Real-IP $remote_addr; proxy_set_header Host $host; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; # WebSocket support proxy_http_version 1.1; proxy_set_header Upgrade $http_upgrade; proxy_set_header Connection "upgrade"; } } ... }This will forward traffic for your domain setup to port 6069 and make use of websockets for that connection. We can can then validate the changes with the following:
# Check the file syntax sudo nginx -t # Restart the server service nginx restart -
Add lets encrypt
For this we will need to add a firewall rule to allow letsencrypt to verify our server:
sudo iptables -L --line-numbers #OUTPUT Chain INPUT (policy ACCEPT) num target prot opt source destination 1 ACCEPT all -- anywhere anywhere state RELATED,ESTABLISHED 2 ACCEPT icmp -- anywhere anywhere 3 ACCEPT all -- anywhere anywhere 4 ACCEPT tcp -- anywhere anywhere state NEW tcp dpt:ssh 5 REJECT all -- anywhere anywhere reject-with icmp-host-prohibitedWe need to add in a line before the REJECT for traffic on port 80 for letsencrypt and port 443 to allow traffic on a secure connection:
sudo iptables -I INPUT 5 -m state --state NEW -p tcp --dport 80 -j ACCEPT sudo iptables -I INPUT 5 -m state --state NEW -p tcp --dport 443 -j ACCEPT # Save the changes sudo netfilter-persistent saveNow we can run certbot, the a cli used for letsencrypt, to verify our domain and update our nginx config.
sudo apt-get install certbot python3-certbot-nginx sudo certbot --nginx -d <Your Subdomain>.<Your Domain>Make sure to select option 2 to redirect traffic to HTTPS.
This should result in 2 server blocks
/etc/nginx/nginx.conf:
server { server_name <Your subdomain>.<Your Domain>; location / { # redirect all HTTP traffic to localhost:6069 proxy_pass http://localhost:6069; proxy_set_header X-Real-IP $remote_addr; proxy_set_header Host $host; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; # WebSocket support proxy_http_version 1.1; proxy_set_header Upgrade $http_upgrade; proxy_set_header Connection "upgrade"; } listen 443 ssl; # managed by Certbot ssl_certificate /etc/letsencrypt/live/<Your subdomain>.<Your Domain>/fullchain.pem; # managed by Certbot ssl_certificate_key /etc/letsencrypt/live/<Your subdomain>.<Your Domain>/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 = <Your subdomain>.<Your Domain>) { return 301 https://$host$request_uri; } # managed by Certbot server_name <Your subdomain>.<Your Domain>; listen 80; return 404; # managed by Certbot } ...Note: If certbot fails here, retry after an hour as most DNS records (like the A record we setup) normally take an hour (but can take up to 48 hours) to propagate.
With this we now have an HTTPS connection we can use for websockets for our domain. Our connection will only stay certified for ~45 days through letscencrypt and will require refreshing our certification, for this I recommend setting up a CRON job on your instance to automate this.
5. Hosting your client on itch.io
With our server now running with a secure connection itch.io will allow the client we upload to it to connect.
To upload our client to the web we first need to export it in Godot as a HTML project. For this make sure to name export the .html file as index.html as itch.io requires this.
This will create a folder with your exported project, which then needs to be compressed to a zip folder.
With your compressed client folder, create a project on itch.io and upload it. Make sure to select your project as HTML.
Finally you can run your web clients, in two tabs and should see two players.
Conclusion
With this you should be able to host your Godot servers for only the cost of a domain name. This is great for hobbyist projects, testing and game jams. I hope this allows you to create more multiplayer projects.









Top comments (0)