Skip to main content

What I set up

A pipeline in GitHub Actions or GitLab CI

Automated checks on every change, then a build of the Docker image that will actually be deployed, pushed to a registry. The steps live in the repository, not in someone’s terminal history.

Deployment to a Linux server

Docker Compose on a VPS or your own server, behind a reverse proxy with TLS. Only the proxy is public; application and database ports are bound to localhost, because Docker’s published ports bypass a host firewall such as UFW.

Secrets and access

Secrets in the CI provider rather than in the repository, a dedicated deploy user and key, and SSH limited to the people and systems that need it.

Rollback

Every release is a tagged image, so going back means deploying the previous tag. Nobody has to reconstruct what was on the server.

Backups and restore

Database backups stored off the server, and a restore tested at least once, so you know it works before you need it.

Handover documentation

How to release, roll back and restore, where the secrets live and what runs where. Everything stays in your repository and your accounts.

How it starts

  1. You email me how the application runs today: where it is hosted, where the code lives and how a release happens now.
  2. I review the current setup and reply with the scope and what I would change first.
  3. I set it up in your repository and on your server, under your accounts.
  4. We go through the documentation together and run the first releases and a rollback with your team.

Where this comes from

I started where a deployment meant running git pull on the production server. Since then I have used GitHub Actions and GitLab CI to build, push and deploy Docker images. The reasons are in Deployment should be boring.

During a production DDoS incident, a container with published ports was reachable directly, even with UFW enabled on the host. That is why I check exposure on every deployment I set up. The incident is described in the case study, and the mechanism in Docker published ports bypass UFW.

Common questions

Do I need Kubernetes?

For one application on one or two servers, usually not. Docker Compose on a VPS is simpler to run and to hand over. I ran K3s in a private lab, not for clients, and I don’t recommend it by default.

GitHub Actions or GitLab CI?

Whichever already hosts your code. I have used both for build and deployment pipelines.

Can you take over an existing setup?

Yes. I start by reading what is already there: how releases happen now, what runs on the server and what isn’t written down anywhere. Then I propose what to change first, keeping the parts that work.

What do I have at the end?

Pipeline configuration and deployment files in your repository, a configured server, and documentation your team can follow without me.

Does it have to be a Laravel application?

Most of my commercial work is in Laravel and PHP. Other web applications that run in Docker follow the same pattern.

To discuss a deployment, email maciej@jasiewicz.pro or see the contact page.