Setting up continuous deployment for your project can be quite tricky. Puppet, Ansible, Chef — all those tools are great, but sometimes you just want something small and simple to use to deploy your pet projects to your virtual or dedicated server.
I want to show you how to setup continuous deployment for your Node.js project with rolling updates, HTTPS and all that fancy stuff in ~10 minutes using Exoframe.
For demo purposes we’re going to be deploying simple Node.js project based on Express.js, you can find the source code (along with all the other mentioned bits) in this GitHub repo: https://github.com/exoframejs/node-cd-demo
If you prefer video format to reading, you can watch me doing the whole walkthrough here:
Once you’d setup the server with your favorite OS, you will need to configure public key SSH authentication.
This is required because Exoframe uses private-public key pairs for authentication process.
If you are using login-password pairs for SSH authentication, I strongly recommend switching to public-private key method.
Also note the part in the linked article about disabling password authentication after you are done with public key authentication part— that is also a must-have, in my opinion.
Once you are done with that — you’ll need to install Docker since Exoframe relies on it for service execution and management.
After you’ve finished with docker, all you need to start Exoframe server is to execute the following command:
docker run -d \
-v /var/run/docker.sock:/var/run/docker.sock \
-v /path/to/exoframe-folder:/root/.exoframe \
-v /home/user/.ssh/authorized_keys:/root/.ssh/authorized_keys:ro \
-e EXO_PRIVATE_KEY=your_private_key \
--label traefik.backend=exoframe-server \
--label traefik.frontend.rule=Host:exoframe.your-host.com \
--name exoframe-server \
Be sure to change the parameters to fit your server — you want to at least:
EXO_PRIVATE_KEYto something unique. It’s used during generation of authentication tokens.
--label traefik.frontend.rule=Host:exoframe.your-host.comto point to your host. It’s used to expose Exoframe server API endpoint.
Important note: This will also start an instance of Traefik that will occupy ports 80 and 443. It is used to route requests to your deployed services, setup HTTPS, etc.
For more detailed explanation of those parameters and startup procedure, see docs in Exoframe server GitHub repository.
Before configuring continuous deployment, we need to make sure that Exoframe server works fine.
To do that, we’re going to install Exoframe CLI locally and deploy our project manually to see if that works.
Currently, Exoframe CLI only works on Node 8+ because it relies on async/await, so make sure you have the latest Node installed.
To install Exoframe CLI locally simply execute:
npm install exoframe -g
Now that we have it installed, we need to point it to our new server. You can do that by executing the following command:
exoframe endpoint http://you.server.url
Once finished, you will need to login into your server by running the following command and selecting the private key that is used for authentication with your server (and possibly entering passphrase for your private key):
After you have successfully logged in, you can deploy your project. But before deployment, we’ll do one last thing — generate a new project configuration file. This can be done by executing the following command inside of the project folder:
The command will guide you through the config creation in interactive manner. For this demo, the only important field there would be “domain”.
Important note: since Exoframe doesn’t know what is entry point of your Node.js project, it’ll simply execute
npm start on deployment and expect service to listen on port 80. So, make sure that you have
start script in your
package.json and use port 80!
Once desired domain for your new deployment has been set, you can deploy the project by simply running this command inside of the project folder:
After Exoframe CLI reports that project has been deployed, you should test its availability on the domain you have entered during config step.
If everything works as expected — we’re green to setup continuous delivery!
We’re going to use Travis-CI for testing and deploying our project.
Here’s a simple
.travis.yml config for Node.js project:
Travis does most of the work on testing Node.js projects for us, so all we need to care about here is specifying language and Node.js version. You can read more about that in official Travis-CI docs.
Now that we have Travis config file and we’ve made sure it works, we need to add Exoframe deployment to it.
Exoframe has a special feature called “deployment tokens” that allows you to deploy projects to your server without the need to login using your private key. So, to setup the deployment, we first need to generate such token. This can be easily done by executing the following command:
Upon execution you should get a freshly generated token that can be used to deploy projects to current Exoframe server.
Important note: Make sure to save the token as there’s no way to read it again, only to generate a new one.
Once you have the token, you want to use Travis-CI encryption system to store encrypted token in your Travis config, like so:
travis encrypt EXO_TOKEN="your-token-here"
After that, you’ll need to tweak the config itself to install Exoframe CLI before running tests and to trigger deployment after tests has been successful.
Config file should look something like this:
After you’ve push it to GitHub, you should be able to open Travis logs and watch your project being deploy to your server.
Note the tiny
-u flag in the config above. That tells Exoframe server to execute a rolling update for the current deployment.
The way it works is pretty simple — it’ll deploy new version, wait for it to start and then tear down the old one, which will result in zero downtime deployments.
Exoframe also supports other project types!
Currently, along with Node.js project, you can also deploy static HTML projects, Docker project and Docker-Compose projects.
If you found Exoframe interesting — give it a shot!
It is available right now on GitHub.
As usual — any feedback as well as contributions are appreciated.