NHacker Next
  • new
  • past
  • show
  • ask
  • show
  • jobs
  • submit
Deploy from local to production (self-hosted) (github.com)
Nelkins 17 hours ago [-]
All of these projects lack server hardening. I think for most devs it would not be a great idea to just point at a server and let 'er rip. I have a pretty extensive cloud-init script I use for this when deploying to a VPS. I workshopped it by finding existing scripts and having a back and forth with Claude. Feel free to roast it :)

https://gist.github.com/NatElkins/20880368b797470f3bc6926e35...

wongarsu 16 hours ago [-]
There is a weird dynamic going on where defaults have become "good enough": ssh with public key configured and password auth disabled, services defaulting to only listening on localhost, etc., but those improvements have also cause people to pay much less attention to server hardening or to checking if any of their services might have unsafe defaults.

The world is made much better by safer defaults, but they also lead to a degree of complacency.

Wilder7977 16 hours ago [-]
I had a quick look, that "deploy" user can run any sudo command without password? It's basically root at that point. I think that forcing a password (maybe using some lax timeout if you don't want to insert it so often) is a much better option. Correct me if I am wrong, but I also see that there are secrets in the file (e.g., gmail SMTP creds). Make sure the file is protected in read at a minimum. If those are your gmail app credentials, they are pretty serious and obtainable by just reading the file (same goes for postfix config).
klysm 2 hours ago [-]
I’ve had this argument so many times over the years, and usually the response comes down to security by obscurity because people won’t know the non-root username
Wilder7977 2 hours ago [-]
That I guess is relevant in the context of brute-force login, which given you only use key with, is not really something I would stress over. However, depending on what that user does, there might be vulnerable services running with its privileges, or there might be supply-chain vectors for tools that user runs.
simpaticoder 16 hours ago [-]
Thank you for sharing, because I didn't know what cloud-init was until your post. I've done something similar, but packaged as a library of bash functions, designed to be called in arbitrary order. I cannot comment on the specific decisions you made in your file, but the fact that a declarative, compact, and standard solution exists for this problem is music to my ears. Out of curiosity, where did YOU learn of the existence of this feature?
shortsunblack 16 hours ago [-]
Cloud init/Cloud config is a standard way to provision Linux hosts. It is slowly being outcompeted by Ignition and the friends, though.
mdaniel 15 hours ago [-]
> It is slowly being outcompeted by Ignition and the friends, though.

I hope not, because I lack enough foul language to describe my burning hatred for Ignition and all its cutesy campfire-related project codenames. Hate-red.

simpaticoder 11 hours ago [-]
Looks like it was invented by Canonical for AWS/EC2 in 2006 (!). It was then gradually adopted by other clouds over the next 10 years or so (GCP adopted in 2013, Azure a couple years later). Linode (Akamai Cloud now, I guess) adopted in 2023. Obligatory xkcd: https://xkcd.com/1053/

This got me to wondering when I first heard about HTML, HTTP, Linux, UTF-8, or any number of things, and from where, how so many of the things I've heard of once and never again, and the many important "standard" things I've never heard of.

codelion 16 hours ago [-]
server hardening is definitely an often overlooked aspect... that gist looks comprehensive. i'm curious, have you benchmarked the performance impact of all those security measures? it's a trade-off, right? some community members mentioned using CIS benchmarks as a starting point, then tailoring from there.
klysm 2 hours ago [-]
Security performance tradeoff is hard, but I always try to keep in mind what the downside to either is. A small performance hit can definitely matter, but for most use cases a security hit will matter a lot more
notarealllama 16 hours ago [-]
Thanks for this, I still provision with a bash script.
Timber-6539 6 hours ago [-]
I wouldn't put some configuration values like no-new-privileges:true in the global docker daemon config. Eventually you will find some app that will break because of this and you will spend hours troubleshooting it if you do not remember this tiny detail.

Something also has to be said for simplicity and redundant choices. For example replacing systemd-timesyncd with chrony is not justified. And some of the recommended sysctl values may be redundant and already the default in the target OS.

fragmede 16 hours ago [-]
port 22 and usepam is interesting. maybe set that to not 22 and not use pam unless you have a specific reason to. didn't dig deep to see if you had one but you're not setting a pam.conf.d file as far as I saw. There's more to pick apart, but if that's the best Claude can do my job is safe for 30 more seconds.

hire a professional to secure your shit.

computerfriend 10 hours ago [-]
Why not use PAM? Or is the issue the missing PAM hardening?
fragmede 7 hours ago [-]
why use pam when ssh has authentication built in? pam is great if you have a reason to use it. I use it on my Mac so I can use my fingerprint for sudo. turning on pam implies you want to do something with it.
dizhn 5 hours ago [-]
I was recently evaluating pam_ssh_agent_auth . It might be that. It allows sudo with a locally installed key.
flaskking 16 hours ago [-]
[flagged]
mediumsmart 18 hours ago [-]
I use rsync in a script. One line builds and the second line deploys - but that pushes to a server someone else has standing on the ground with a disk in it that hosts the site I myself made on a local machine. If I self-hoist the production server into my flat, couldn't I just copy the folder without the internet like from local to local?
rad_gruchalski 17 hours ago [-]
No need to even copy a folder, simply link it.
indigodaddy 19 hours ago [-]
This seems cool and all but it's fairly trivial to docker compose whatever stuffs/apps you want and install caddy as the reverse proxy on the host (I normally don't do caddy in a container but it might be better to)

You have to setup docker compose files with airo it looks like in any case, so this just simplifies the caddy part? But caddy is so simple to begin with I'm not sure the point..

delduca 18 hours ago [-]
Docker compose + Cloudflare Tunnels is my current setup, no need to deal with SSL, have a public IP address, and if you make use of Tailscale, you do need any open ports, witch is extremely secure and robust.
ratorx 19 hours ago [-]
Does it even configure caddy? I can’t see how the caddy config could be generated from the env.yaml (unless it relies on the directory name etc for the path).

Seems like something that could have been solved with just docker compose (by setting a remote DOCKER_HOST). If you need “automatic” proxying, then traefik can do it off container labels.

timdorr 17 hours ago [-]
Nope, it just copies over a hand-made Caddyfile and restarts a docker container that you need to already be running: https://github.com/bypirob/airo/blob/1a827a76f2254e5ca4f4ba4...

This looks extremely barebones and makes a large number of assumptions in its current state. This is better as a Show HN after some more dev work has been completed.

notpushkin 10 hours ago [-]
Agreed – it’s a bit too early to publicize this. Lots of great alternatives discussed here though!

Maybe I should try to Show HN my Docker dashboard, https://lunni.dev/ :thinking:

globular-toast 6 hours ago [-]
Surprised it doesn't use caddy-docker-proxy to automatically route traffic to your compose set up. You could just do that in dev and have a very simple compose override for prod that changes the domain names etc.
hn_rob 6 hours ago [-]
I have been using a makefile where each target executes a shell script snippet to build, push or deploy containers. The problem is that with simple docker build it doesn't recognize modified code files and uses cached layers. To pick up changes in the code I always have to build with --no-cache which is inefficient. I wonder if Airo can detect changes in the code and rebuild only the image layers that need to be rebuild.
globular-toast 6 hours ago [-]
This sounds like a misconfiguration on your part. I've never had this problem with docker before. Are you sure it's not your makefile skipping something because you haven't made the docker bits phony targets (if you're using make as a "script runner", everything should be a phony target. A sign that you're using the wet tool, but I digress).
scottydelta 17 hours ago [-]
I have been using coolify on a bare metal server and it has been such a great experience.

The ability to spin up services is crazy good and easy. I was able to evaluate n8n, windmill.dev and prefect in 3 hours because I was able to quickly setup these clusters and test them. And final thing was to compile my code as docker container and spin it up on coolify within mins with custom domain and ssl.

How is it different and eaiser than coolify kinda setup?

tharos47 8 hours ago [-]
How do you handle backups ? I recently setup coolify and installed the included WordPress. WordPress was broken by a failed module install, I wanted to restore a backup and didn't find a way to backup only one service/stack.

Compared to simply docker compose isolated in a vm/lxc container it was not a particularly better experience.

I also wanted to use cloudflare tunnels instead of exposing the server on the internet and it seems coolify really prefers to work directly on the internet (lacking reverse proxy doc, ...)

replete 15 hours ago [-]
Coolify will be great, 6 months ago however I experienced so many bugs around docker deployments I just couldn't trust it for production. Hopefully the new hires will make continued progress because there are some pretty great workflows possible. Already though, it is extremely cool to run your own platform
chris_pie 15 hours ago [-]
There's also a long standing issue of random peaks to 100% CPU, that they don't seem to be able to fix.
jilles 17 hours ago [-]
I did the same. Really enjoyed Coolify but at some point there was too much magic.

I’m now using Dokku and can’t imagine using something else.

sameklund 16 hours ago [-]
Considering both of these right now. Why was Dokku so much better for you?
notpushkin 11 hours ago [-]
I’m working on Lunni – similar to Coolify, but centered around compose files (hopefully that’s less magic!): https://lunni.dev/

Would love to hear your thoughts if you give it a try!

sameklund 8 hours ago [-]
Looks like this is a web UI for docker swarm? Does it have additional PaaS-like features? I think I would probably just use Portainer if I wanted a GUI. Unless I am missing something?
notpushkin 6 hours ago [-]
Lunni is similar to Portainer. (And it uses Portainer as the backend, actually!)

Before I started Lunni, I was using Portainer myself, but it got too painful. Here are some paper cuts I’m trying to solve with Lunni:

- I only manage one cluster (of one server), but I still had to select endpoint every time. In Lunni, the first thing you see when you log in is the status of your stacks/projects

- I use Traefik with routing config living in service labels. It’s a huge snippet, impossible to remember, which I had to copy from project to project. In Lunni it’s autocompleted for you: https://lunni.dev/docs/deploy/#:~:text=This%20is%20quite%20l...

- When you look at the service logs in Portainer, they refresh once in a while and throw away your scroll position, which is super frustrating. In Lunni, it works as you’d expect. As a bonus, you can copy a link to a log line (e.g. if you want to share it with somebody or just bookmark it)

- If you need to create a Docker config or secret for a stack in Portainer, you have to go to another dashboard section, make a config yourself, then copy the name to your stack. In Lunni, you can do that right on the New project page: https://lunni.dev/docs/configs-secrets/

- ...and a lot of other things like error messages that don’t disappear in 5 seconds, before you’ve had a chance to read them

Basically, I’m trying to make a Portainer that is a pleasure to use. Maybe it’s not as close to Coolify as I thought, but I’m trying to maintain a more PaaSy feel than Portainer. Some things you’d expect from a PaaS, like a built in CI and automated DB/volume backups, are also on the roadmap!

kilroy123 17 hours ago [-]
Same here but I've certainly ran into some rough edges. Especially with some of the more complicated one click services.

Overall, I like it but I wish it was a bit more polished.

barrettshepherd 19 hours ago [-]
What’s the advantage of this over Kamal? (https://kamal-deploy.org/)
ngrilly 18 hours ago [-]
I like that it's a single file executable. But Kamal offers much more, for eample zero-downtime deployment.
oulipo 18 hours ago [-]
Also Dokploy, Dokku, Coolify and similar
ajayvk 15 hours ago [-]
Another option you could consider is a tool I have been building for deploying webapps across a team. https://github.com/claceio/clace has the usual deployment related functionality like gitops, TLS certs.

It has some unique features like supporting OAuth authentication for the apps, staging env for each app (code and config changes are staged before deployment), supporting declarative update, supporting hypermedia based apps natively etc.

notpushkin 11 hours ago [-]
This is so cool! The scope is a bit broad (it’s a build tool, DevOps tool and a hypermedia app framework?) – maybe you could split this into multiple projects and start a whole ecosystem?

I’m also working on a deployment tool, though not nearly as ambitious – it’s just a Docker dashboard based around Compose files: https://lunni.dev/ (though it does everything Traefik does, and GitOps are also definitely on the roadmap)

ajayvk 10 hours ago [-]
Thanks. Clace is built for teams to be be able to deploy internal tools (Streamlit/Gradio etc). That use case requires some extra features (OAuth/Auditing/Declarative config etc). Kubernetes with ArgoCD plus IDP seems to have become the default solution, which is overkill for such use cases.

The Hypermedia based app support was added to be able to build a management dashboard for Clace itself, without going down the SPA route. It made sense to expose that for end uses to be able to build their own apps.

qudat 17 hours ago [-]
I just use a tunnel service to self host web services, works great and is cheaper than a VPS: https://tuns.sh
__jonas 17 hours ago [-]
I've got a kind of similar setup but what I've been doing is instead using a registry I'm just pushing the images along with the compose file onto the server directly with rsync to keep things even simpler. Would be nice to have a proper tool like this to automate that (I'm just using a bespoke shell script).
zelifcam 19 hours ago [-]
Imagine if people just used the tools themselves instead of creating yet another layer in hopes of simplifying something that can already be done with a few lines on a bash script.
cdfuller 18 hours ago [-]
Agreed. This project isn't that upfront this is a wrapper around 4 commands. Docker build, docker push, docker pull and compose up.
MyOutfitIsVague 18 hours ago [-]
Whew, you're not joking. This whole thing is 156 lines of Go. I'd probably have just used a shell script for this kind of thing.
xnyan 11 hours ago [-]
I know ansible is not sexy or resource efficient, but it would be a handful of lines in a single task.yml and it would work reliably out of the box. Previously the part that was too much effort for me to be reliable was often bootstrapping the python environment on the host, but uv has been a game changer (at least it has been from my team) in terms of being able to efficiently and reliably ensure the exact python environment we want.
0xbadcafebee 17 hours ago [-]
I think we can all agree that any Go program that just executes some other program, is way better than a shell script!

I mean, what if you needed to change the way it worked? With bash you'd have to open a text editor, change a line, and save the file! And on top of that you need to understand shell scripting!

With Go, you can set up your development environment, edit the source code, run the compiler, download the external dependencies, generate a new binary, and copy it to your server. And all this requires is learning the Go language and its development model. This is clearly more advanced, and thus better.

indigodaddy 13 hours ago [-]
Haha, nice
morcus 18 hours ago [-]
For small projects you can also add something like Watchtower to your compose file and then you need only build and push the image.

And I assume you want to be building once to test your changes anyways, so you really only need to push.

ianburrell 11 hours ago [-]
This is perfect use for Make. Have command for build, push, and deploy. Then have one to do them all together. The advantage is can do individual commands, and put one for building and testing locally.

Long scripts suck in Makefile, but can call external scripts for anything big.

xandrius 18 hours ago [-]
Exactly, for over 4 years I've been using my trusty 10 lines of bash (most of them is confirmation) to deploy in seconds and with 0 downtime. I should probably opensource it, lol
Wilduck 17 hours ago [-]
I know you're joking a little, but I personally would love to see them! I'm very interested in how people manage simple deploys.
tbocek 7 hours ago [-]
Here is mine, I have a docker compose file locally, and this deploy.sh script deploy to my remote machine. That also means that my remote machine is building the image. And I have not found a good solution for secrets/env files yet:

  #!/usr/bin/env bash
  
  export DOCKER_HOST="ssh://username@host:port"
  docker compose up -d --build
xandrius 2 hours ago [-]
For secrets, just literally have an ssh command which reads the local .env file and uses them to start the server with them as arguments/env vars.
polishdude20 18 hours ago [-]
My method is I push my code to master and then ssh to my server, git pull and restart the server
Etheryte 15 hours ago [-]

  while true; do git pull && sudo reboot; done
cryptbro 15 hours ago [-]
[flagged]
12 hours ago [-]
Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact
Rendered at 14:53:33 GMT+0000 (UTC) with Wasmer Edge.