How to Host your Applications With HTTPS for Just a Few Bucks

Updated

Why Should You Read This Article?

Let me explain, what the results will be. If they sound interesting for you, then you know that you should read this article.

What will you get by following this tutorial:

  • An option to host your private applications
  • Make your apps accessible over https via the web
  • An automated deployment pipeline for your applications via GitHub actions and packages (using another container repository is not much effort)
  • Very low manual effort

How much $$$ will it cost:

  • Domain costs 10$/year
  • Server costs (there are many websites that allow you to host a virtual server for under 2$ / month)

So in total you can keep it under 3$/month if you use vServers and a domain from a cheaper domain provider. For this price you can host not one but many applications/servers.

Prelude

  • Many times I wanted to host my applications in the past, but there was no simple and cheap way, in the end we are talking about fun projects and not about the next big start-up
  • Not only do I want to host my apps, but also apps from other developers like game servers
  • I also did not want to re-do all the steps to deploy applications so I would need to invest the time to create a abstract solution that can be applied to all projects
  • What about AWS? It offers a lot of fully managed workflows. However, they are expensive so I want to propose an alternative.

What do you need first:

  • A Github account
  • Understanding of docker and docker-compose
  • Understanding of Github Actions
  • A domain to host your apps on (with access to the DNS records)
  • A app that you want to deploy and a Dockerfile to containerize it
  • A Linux server instance (you can use any vServer provider that you find, for instance, Netcup offers very cheap vServers with great reliability for private projects)

Setup your Domain Properly

To redirect all sub domains of our domain “domain.com” we need to add an A-Record that points ‘*’ to your server’s ip. In ‘Godaddy’ it might look like the following figure:

domain-provider-setup

Create a Github Repository for Your Server Administration

We want to avoid any manual steps in setting up the server. All our configuration and setup should exist as code. For this we will use Ansible. Never heard of it? It is basically a tool that allows you to execute commands on remote servers with definition files that are called ‘playbooks’.

I already created most of the things you need in a abstract way. You can just reuse the existing tools. To setup a project that allows us to manage our server we will do the following:

  • Create a repository based on this template by clicking ‘Use this template’: Template
  • Add all secrets that are mentioned in the readme to the repo secret list (keep in might that the environment_variable secrets are not necessary if your applications do not require any environment variables)
  • PS: Secrets can be added by going to your repositories settings > Secrets > Actions > New Repository Secret.
  • The secrets need to have the same names as in the README and they need to have the values that you see in the description in the README.
  • PS: If you need to use a SSH_KEY then you need to checkout the documentation of this action: dawidd6/action-ansible-playbook@v2

What Projects do You Want to Deploy?

Now that we have our skeleton setup we can define the projects that we want to deploy.

  • Go to the docker compose file of your repository
  • Add the docker containers that you want to execute similar to the code example you see down below

This is how an example configuration might look like.

0  application:
1    image: ghcr.io/flamestro/example-application:main
2    pull_policy: always
3    expose:
4     - 8080
5    networks:
6      service_network:
7    cpus: 0.6
8    mem_reservation: "200M"
9    mem_limit: "600M"
10    environment:
11      ENV_VAR_ONE: ${ENVIRONMENT_VARIABLE_ONE}
12      HTTP_PORT: 8080
13      VIRTUAL_HOST: your.domain.com
14      LETSENCRYPT_HOST: your.domain.com
15      LETSENCRYPT_EMAIL: "[email protected]"

Note: Without setting up anything else this will already ensure HTTPS. Your application will be reachable under value of the VIRTUAL_HOST environment variable. You do not need a port to reach your app in the browser as it will run on HTTPS. This is because of the HTTP_PORT variable which tells the configuration to map your internal application port to HTTPS. In this case we are saying “map the apps 8080 port to the external 443 port”. This also means that the app does not need to know that it is using HTTPS.

The ENV_VAR part can be looked into, if you are curious how to pass secrets or configuration securely to your applications.

Do not get confused by the expose: 8080. It works together with the networks: service_network part. Your app will be exposed inside of the docker-compose network service_network and NGINX will proxy it to the outside world. However, it is not exposed directly to the outside world.

How to Host Your App and Packages

If you came up to this point everything should already be working for you. But if you need to know how to deploy application packages to Github’s container registry (ghcr.io), then this part might be interesting for you.

I do not cover containerization of your app in this part. So for the next steps to work you need a Dockerfile in the root of your project that can run the app in the state you want.

Afterward, you can add a Github workflow for your app. It should contain this two steps:

0 - name: Publish Docker Image to Github Packages
1   uses: flamestro/[email protected]
2   with:
3     token: ${{ secrets.GITHUB_TOKEN }}
4
5 - name: Dispatch Deploy Event to Deployment Repo
6   uses: flamestro/[email protected]
7   with:
8     token: ${{ secrets.PAT_DISPATCH_SERVER_DEPLOYMENT }}
9     event: TRIGGER_DEPLOYMENT
10     repository: ${{ secrets.DEPLOYMENT_REPO }}
11     owner: flamestro

To use the GITHUB_TOKEN you need to enable write access for it in your repo -> settings -> actions -> general -> read and write access.

As you can see this pipeline steps have three secrets that they use. As the GITHUB_TOKEN is a automatically provided secret we will only take a look on the other two.

  1. PAT_DISPATCH_SERVER_DEPLOYMENT: This secret contains a PAT that allows has a repo scope. This is needed to dispatch an event on the server-control repository and trigger a remote deployment.
  2. DEPLOYMENT_REPO: The name of your server-control repository.

The first step will create and upload an image to your Github container registry.

The second step will notify the server-control project of a new deployment.

You now have a way on how to setup your apps and how to run them on a server. If you have any further questions feel free to leave a comment and if the guide helped you, you can checkout the nice clapping animation.