These are the instructions for the Server Template for Busy Hackers.
We'll be using DigitalOcean to spin up a server (or droplets as they're called). DigitalOcean is a popular choice for developers because of its friendly user interface and good customer support. Their prices are competitive and they offer good value for what you pay.
You can use my referral link to get $100 in credit valid for 60 days.
A DigitalOcean API key grants the script access to create a server in your behalf. To create a token, please follow these instructions: https://www.digitalocean.com/docs/apis-clis/api/create-personal-access-token/
Make sure the token has write permission. Add the token in vars/main.yml
file:
do_api_token: "your_api_token"
Ansible is an open-source software used to automate IT infrastructure. It's the underlying tool used by the script to provision & configure the server and deploy your applications.
The easiest way to install Ansible on macOS, is to use Homebrew:
brew install ansible
Linux users can install Ansible from apt.
If you're on Windows, you'll need the Windows Subsystem for Linux (WSL). The official installation instructions from Microsot explain how to install WSL on Windows 10. After having installed WSL, you can install Ansible through apt similar to Linux users.
In case you already have Ansible installed, make sure you're using version 2.9 or higher. Older versions haven't been tested and they might not work.
The script assumes you have an SSH key pair on your machine stored at the default location. The public key will be added to your DigitalOcean account, which will then be used to authenticate with the newly created server.
If you don't have an SSH key pair, you can create one in just 4 steps.
If you wish to use a different key pair than the default one, change the do_sshkey_public
and do_sshkey_private_path
variables in vars/main.yml
file.
Node.js 14.x will be installed on the server to run your applications. If your apps need to use a different Node.js version, you can change this with the nodejs_version
variable.
All applications will use the same Node.js version, so make sure you choose a version that works with all of them. I might add support for app specific Node.js versions in the future if there's enough interest. Send me a quick email at hello@maximorlov.com if you need this feature.
By default, the script will create a $5/month server in the Amsterdam region. You can change the size and location in vars/main.yml
file with the droplet_size
and droplet_region
variables, respectively.
Other variables in the same file that you might consider changing are:
droplet_name
(default: "mydroplet") - Name of the dropletserver_user
(default: "myuser") - User that will be created on the server
To create and configure a server, type in the following command:
ansible-playbook bootstrap-server.yml
It will take a few minutes to complete. Sit back and relax ☕.
After a while you should see a success message with the IP address of your new server together with the SSH command to log into the server if you ever need to.
Before you can deploy your first app, you'll need to create a Github token. This token will grant the server access to your private repositories. It will also be used to create a repository webhook so your app is automatically deployed on every push.
To create a token, go to your Github access tokens and click on "Generate new token". Give the token a name (eg. "server template") and select the following scopes:
- repo - Full control of private repositories
- admin:repo_hook - Full control of repository hooks
Click "Generate token" and copy & paste the token in vars/main.yml
:
github_token: "your_github_token"
First, fill in your Github username in vars/main.yml
:
github_username: "your_github_user"
A requirement for your app is that it needs to listen on a dynamic port passed in as the PORT
env variable. If your application uses a hardcoded port, I recommend you change it to:
// Use dynamic port from `PORT` env var if it exists, otherwise 3000
const port = process.env.PORT || 3000;
To deploy your application, you need to pass in 3 variables through the command-line:
github_repository
- You app's repository name on Githubbranch
- Branch name to fetch and deploy. Automated deployments will occur on pushes to this branchentrypoint
- Application entry point (eg.: index.js)
For example, to deploy a nodejs-demo
application from the main
branch with index.js
as the entrypoint, you'd run:
ansible-playbook deploy-app.yml --extra-vars "github_repository=nodejs-demo branch=main entrypoint=index.js"
The script will look in the envs
folder for a valid YAML file named after the application, and if it finds one, it will pass the environment variables to your app. For example, if you used "github_repository=nodejs-demo ..."
during app deployment, then the script will look for a envs/nodejs-demo.yml
file.
If all went well, your application is deployed successfully 🚀.
A message will be printed to the console with an URL link to view your app. The link has the form of http://{server-ip}/{github_repository}. To access your application from a custom domain, proceed to the next step "Domain and SSL".
Run this script for each application you wish to add to the server.
Your application is set to automatically deploy on each push to the branch specified above. Try it out! Make a small change, push to Github, and it'll be live immediately 💫.
After you have confirmed your application is up and running, you can point your own domain to the server. This allows you to access your application by typing the domain in the browser instead of the server IP.
Log in your DNS management tool and make sure the A record points to your server IP address. This is usually where you bought your domain or, if you've changed the nameservers, the owner of those nameservers. If you don't know how to create/change an A record, this Google search query might help "how to set A record <dns_management_tool>".
It can take several hours up to a day for the changes to take effect. You can go to https://dnschecker.org/#A and type in your domain to check if the domain resolves to your server IP address.
Note: if you're using a proxy, say Cloudflare's "yellow cloud", your domain will resolve to Cloudflare's servers to protect your real server IP.
Under the hood, we use Let's Encrypt to generate a trusted SSL certificate for your application. Let's Encrypt requires an email address to send notifications about the certificate. Before you can generate an SSL certificate for your application, you need to fill in your email in vars/main.yml
file:
letsencrypt_email: "your_email"
To generate an SSL certificate, you pass in the name of your application that's installed on the server and the domain, or subdomain, to serve your application from (eg.: mydomain.com or subdomain.mydomain.com).
For example, to generate an SSL certificate for application nodejs-demo
with mydomain.com
domain, you'd run:
ansible-playbook generate-ssl.yml --extra-vars "github_repository=nodejs-demo domain=mydomain.com"
Note: The script will fail to generate an SSL certificate if your domain isn't pointing to the server. You can wait for the DNS to propagate and retry later.
If the script was successfull, you can navigate to your domain and your application should appear with a green HTTPS lock next to the URL 🔒.
The SSL certificate is valid for 90 days. When the certificate is close to expiration, it will automatically renew for another 90 days. The certificate will be renewed continuously so you don't have to worry about expiring certificates ever again.
To update an application's env vars, you simply change its corresponding YAML file in the envs
folder and run the update-env.yml
script.
To restart an app named nodejs-demo
with the latest env variables from envs/nodejs-demo.yml
, you'd run:
ansible-playbook update-env.yml --extra-vars "github_repository=nodejs-demo"
Note: If you remove an env variable from the file (or remove the entire file), the env variable will also be removed from the production app. In that sense, the YAML file in the envs
folder is the source of truth for your app's env variables.
To completely remove an application from the server, run the remove-app.yml
script with github_repository
variable equal to the application you wish to remove.
To remove an application named nodejs-demo
, you'd run:
ansible-playbook remove-app.yml --extra-vars "github_repository=nodejs-demo"
This will stop the application and remove all traces of it on the server. Changes made outside the server, such as the webhook for auto-deployments on Github, are undone as well.
- Were the instructions clear enough for you to follow along?
- Did you bump against some issues, or was it a smooth process?
- Are you missing a feature that would make your life so much easier?
- Perhaps you're so thrilled with your new setup, that you just want to share your excitement
I'd like to know! Feel free to send me an email at hello@maximorlov.com. You can also reach out to me on Twitter, my handle is @_maximization.
Многовато шагов бро.