
Host Your Blog on DigitalOcean with Docker, Nginx and Let’s Encrypt - carlopellegrini
https://www.archij.com/host-your-own-blog-on-digitalocean-with-docker-nginx-and-letsencrypt/
======
cyphar
> volumes: - /var/run/docker.sock:/var/run/docker.sock:ro

Please for the love of all that is holy, do not ever do this! Giving access to
the host's Docker socket is _equivalent_ to giving a container _unrestricted
root access to your host_. Mounting the socket read-only doesn't protect you
in any way either, because you can still connect to and write to the socket!
Seriously, try it:

    
    
        % touch /tmp/docker.sock
        % mount --bind -o ro /var/run/docker.sock /tmp/docker.sock # this is -v /var/run/docker.sock:/foo:ro
        % docker -H unix:///tmp/docker.sock run --privileged -v /:/host -it ubuntu bash
        # # I couldn't write to it, but I can connect and write to the connection...
        # cat /host/etc/shadow # whoops!
    

(The full container escape is left as an exercise for the reader. It's pretty
trivial though.)

To be fair, there are unix-like DAC controls that do restrict this somewhat
but given that most people run containers as root or they don't use user
namespaces this is still an issue.

Please stop doing this, please stop telling people to do this, and please stop
making images that access docker.sock. I understand that this is something
that a lot of people do, so it's obviously not exclusively the fault of the
author for doing what the majority of people appear to be doing, but I think
that this deserves to be said much stronger than it was in the past (people
still expose Docker over the internet -- which is literally a free root-level
RCE for anyone who figures out you're hosting it).

And yes, AuthZ plugins exist but nobody really uses them as far as I'm aware
-- and personally (as someone who maintains container runtimes and other low-
level container tools) I would not feel confident in depending on any AuthZ
plugin's profile to protect against a container escape where you give
unprivileged users access to /var/run/docker.sock. Even if I were to write
one.

~~~
benatkin
This is where it comes from and that's probably why it isn't explained in the
post: [https://github.com/JrCs/docker-letsencrypt-nginx-proxy-
compa...](https://github.com/JrCs/docker-letsencrypt-nginx-proxy-companion)

It seems like if the author(s) of docker-letsencrypt-nginx-proxy-companion had
assumed something like docker compose or kubernetes that neatly handles
sharing volumes between containers, they probably wouldn't have made the
mistake of giving a docker container access to docker for such a trivial use.

I disagree that there's never a good reason to do this though. A docker
control panel, or a CI or FaaS that spawns docker containers, can be a good
reason to do this. [https://jpetazzo.github.io/2015/09/03/do-not-use-docker-
in-d...](https://jpetazzo.github.io/2015/09/03/do-not-use-docker-in-docker-
for-ci/)

BTW there's no escaping the container when you're doing this intentionally.

~~~
cyphar
> I disagree that there's never a good reason to do this though.

The number of cases where it is an acceptable idea to do this (compared to the
number of cases where people do this because they read it on a random blog
post) is so small that it is statistically insignificant. In my view, it is
much better to tell people to _never_ do something which is very rarely
useful. People who know better would know when to ignore that warning (which I
would hope would be the sort of people who would write a CI or FaaS), while
those who don't know better likely wouldn't use it in a way that is "safe".

The blog post you link to is quite old (this was at a time when most users
were well aware of what docker.sock did -- so much so that vulnerabilities I
helped find in Docker from that time were not regarded vulnerabilities because
they required docker.sock access!). I agree with Jerome's point which was to
dissuade usage of Docker-in-Docker. His point _was not_ that bind-mounting the
docker.sock is generally an okay thing to do -- and as I said I think that we
should be far more vocal about how dangerous this is (because people don't
listen otherwise -- as has been shown by the fact that there are still plenty
of users that have Docker listening on a TCP socket without client
certificates).

> BTW there's no escaping the container when you're doing this intentionally.

I don't know what you mean by this -- if you bind-mount the docker.sock inside
a container that container can _trivially_ get root access on the host (AuthZ
plugins can make it harder but as I said they are rarely used and cannot
protect you from sufficiently clever attackers). My demo with 'mount --bind'
was just to show how it worked, the same thing happens with '-v' (which is
just a bind-mount under the hood).

Now, if you argue that the code in the container is always something you trust
(which I think is a questionable assumption as it assumes that your code is
not exploitable) then sure -- if all the code on your machine is safe you have
no worries. But then the obvious question arises -- why do you need the
isolation properties of containers in the first place? Why not just run in a
chroot?

~~~
icebraining
_why do you need the isolation properties of containers in the first place?
Why not just run in a chroot?_

Docker containers are about more than isolation, they're also packaging. In my
case, I already have a docker-compose.yaml with five services; adding another
program as a chroot instead of a sixth service would significantly increase
the installation complexity.

I do agree with you that mounting the Docker socket should never be
recommended on a tutorial.

~~~
cyphar
Right, there is a tooling argument. My point was that you can get most of the
packaging with just chroot -- images are just tar archives at the end of the
day.

But I might be biased given that while I've worked on both runtimes and image
tools, runtimes have a lot more interesting problems so I tend to focus more
on them when discussing the benefits of containers. :P

------
AndrewStephens
I I’m not going to tell people not to do this, but in my opinion this is
massive overkill for a simple blog. Why use docker when you can just run nginx
on the host with certbot for LetsEncrypt.

I guess docker gives you some flexibility for rollover and load balancing, but
a single droplet will handle huge amounts of traffic for static sites.

~~~
zawerf
In some sense everything is massive overkill for a "simple blog". You should
just pay for medium/wordpress/ghost or use a static site hosted on github
pages.

I personally fell for these posts a while back and regretted spending time on
it. They don't tell you about the crazy amount of sysadmin skills that you
need to get it up and running:

Do you need to worry about updates/security patches? How do you configure
firewalls? How do you configure ssh settings? How would you even audit
unauthorized logins? Where are logs stored? Are they rotated? Are they backed
up? Are there backups? How do you restore from backups? How do you configure
nginx? How do you configure certbot? How do you check if cron is running
correctly? Do you ever look at access/error logs? How do you keep services
running upon restart? How do you get notified of problems? How do you monitor
uptime?

Each individual question will take minutes to hours to research and will open
up new rabbit holes.

~~~
Jedi72
That's why I think these blogs/projects are useful. Or should people learn all
this stuff first time they run a real app in production?

~~~
delinka
Most bloggers aren't ever going to "run a real app in production."

Most {net,dev,sec}ops engineers aren't writing blogs.

~~~
peatfreak
> Most {net,dev,sec}ops engineers aren't writing blogs.

Unfortunately, in my experience this is true. It's not for lack of motivation
or desire, it's because my day job is stressful and tiring. The last thing I
want to do when I come home in the evening is to spend my valuable personal
time writing a blog about what I did at work. I would rather spend time with
my family, or do something like that.

Of course, I could try to schedule time during work hours to write a blog on
the company website by talking with my manager about it. Unless this advances
any strategic or political agenda, it's unlikely to happen.

~~~
apatters
You could write about non work stuff that interests you, and only do it on
occasional instances where you feel like writing, and pay someone like
wordpress.com a pittance to handle the tech. This is what most web logs were
like in the beginning.

I write a post on my blog about my interests once every month or two, and
maybe crosspost it to Facebook, but I like that I get to write down my
thoughts on a site I own.

If you don't get much enjoyment out of writing period though, not much reason
to blog.

~~~
jamietanna
I personally blog about things I've found while working that have been a pain
or a "oh hey, cool!" that I've not seen documented anywhere easily, so I write
about them under the term "blogumentation" (blogging as a form of self-
documenting)
[https://www.jvt.me/posts/tags/blogumentation/](https://www.jvt.me/posts/tags/blogumentation/),
reasoning found in
[https://www.jvt.me/posts/2017/06/25/blogumentation/](https://www.jvt.me/posts/2017/06/25/blogumentation/)

I've found it useful for myself and colleagues, but also it's really awesome
seeing hits from Google and other mediums where people are obviously finding
it organically and sharing around through various means. Helping others find
new / better ways to do things is really awesome

------
StavrosK
Having been down that path, don't do this to yourself. Just use a static site
generator and Netlify, and save yourself countless hours of work and headache.

~~~
akuji1993
Yeah there really isn't any reason to do this other than wanting to
specifically use these technologies.. Way easier with generators. Also you can
save a lot of money by hosting it cheap instead of DigitalOcean.

------
newscracker
For blogs that are “small” and/or expect low traffic, if someone doesn’t want
to use free services, my recommendation would be a static site generator that
pushes content to a site on Nearly Free Speech (nearlyfreespeech.net). It has
a very simple way to create (and continuously renew) a letsencrypt TLS
certificate. The cost would be USD 1.5 a month (or a bit higher than that) for
what’s classified as a “production site” there.

One drawback with NFSN is that it requires people to be somewhat tech savvy
and know how to manage sites, probably use ssh, etc. If you’re someone who can
use S3 or this solution, then you’ll find NFSN easier and cheaper for _this
use case_.

~~~
exolymph
I love NFSN. I wrote a detailed review a while back:
[https://winningwp.com/nearlyfreespeech-web-hosting-
review/](https://winningwp.com/nearlyfreespeech-web-hosting-review/)

(Not much has changed since then, and I'm still a happy customer.)

~~~
newscracker
Nice writeup. Thanks for that!

------
blairanderson
Absolutely do not do this.

host your blog on [https://pages.github.com](https://pages.github.com) or
[https://www.netlify.com](https://www.netlify.com)

~~~
ILikeConemowk
shout-out to gitlab pages, I use it and love it.

~~~
dsumenkovic
Awesome, thank you for your kind support. We really appreciate that.

~~~
mcny
I think gitlab pages is a great way to introduce people to the philosophy of
gitlab.

I could imagine a pipeline setup in the future (with the help of web IDE) that
will allow authors to write and commit new articles, for editors to edit them
and sign them off to the publisher, and the publisher to publish articles to a
static site without leaving the browser. Thoughts?

------
guu
To everyone saying "use a static site", this deploys Ghost which is a blogging
application that provides an admin interface to create and edit posts.

Yes, you can use something like Netlify CMS or Contentful with a static site
to get an admin interface, but those would require additional setup or payment
beyond github pages or a netlify account.

------
juanuys
It'd be nice to see a follow-up post on how to keep this setup up-to-date with
the latest security fixes without service disruption.

~~~
peterwwillis

      ~$ docker-compose pull
      ~$ docker-compose up -d --build
    

The compose files are already using latest, so this pulls the latest images,
rebuilds images with any new code, and restarts the services.

~~~
subway
assuming jwilder publishes updated images..

~~~
peterwwillis
Oh, for upstream/base? If a Docker Hub image was set up with automated builds,
it would automatically rebuild the image once its base was rebuilt. It looks
like _nginx_ was set up this way, but _nginx-proxy_ was not. So you have to
rebuild _nginx-proxy_ manually.

    
    
      ~$ git clone https://github.com/jwilder/nginx-proxy
      ~$ cd nginx-proxy
      ~$ docker build -f Dockerfile.alpine -t my-own-tag-name/nginx-proxy:alpine .
      ~$ cd ..
      ~$ sed -i -e 's/image: jwilder\/nginx-proxy.*/image: my-own-tag-name\/nginx-proxy:alpine/' docker-compose.yaml
    

Alternately, you could fork the _nginx-proxy_ repo, build it, push it to your
own Docker Hub account, and add the Repository Links[1] back to _nginx_. Then
you could use TravisCI to automatically pull in and rebuild changes from the
parent _nginx-proxy_. This way you get automated builds when base is updated,
and when _nginx-proxy_ is updated.

[1] [https://docs.docker.com/docker-hub/builds/#repository-
links](https://docs.docker.com/docker-hub/builds/#repository-links)

~~~
subway
Yes, it is entirely possible to do the right thing.

The trouble is 9 times out of 10, the only place you find it documented is in
some random forum post where cargo-cult silliness gets critiqued, rather than
by the folks publishing these how-tos.

~~~
peterwwillis
These aren't even how-tos, they're clickblogs. If you'd like to contribute to
actual HOWTOs for this kind of stuff, I'm building a wiki...

~~~
kkarakk
link to the wiki for a noob?

------
abraham_lincoln
Is this the proper way to share file sockets?

Also, why Docker and not just an Ansible script?

update:

Found this...

[https://github.com/jkap/ansible-ghost-
letsencrypt](https://github.com/jkap/ansible-ghost-letsencrypt)

~~~
peterwwillis
Why not Terraform? Why not Puppet? Why not X? Pick your poison. But it does
seem simpler to not have to learn Ansible if you're already using Docker.

The example you give has 6 config files.... the linked article uses 1 config
file. _shrug_

~~~
abraham_lincoln
So if you know Docker, you shouldn't know how to do things without a
container?

~~~
manigandham
Nobody said that.

But yea, when using Docker already, why not? It's quick and easy compared to
all the alternatives.

~~~
abraham_lincoln
Why add an additional layer of abstraction?

Really, you don't even need Ansible.

Just ssh into the box, apt install nginx, run the Let's Encrypt script and
install Ghost.

~~~
peterwwillis
The docker-machine command creates the droplet for you, and then docker-
compose runs everything for you. It's two commands and one config. It's
repeatable, automated, fast, simple, and complete.

But, sure, you could do it in a more complicated way, or a more manual and
time consuming way that isn't documented or automated. I think that's called
the "job security" method.

~~~
abraham_lincoln
How many static blogs are you deploying?

Shouldn't we also be using k8s to orchestrate all the blogs?

~~~
akvadrako
Yes, k8s would make it even easier, if you had access to a hosted k8s cluster.
But that isn't what DigitalOcean provides.

~~~
icebraining
It does now:
[https://www.digitalocean.com/products/kubernetes/](https://www.digitalocean.com/products/kubernetes/)

------
tomcam
This is NOT meant to be incendiary. I'm trying to learn. Why not use Netlify
instead? It seems to have everything you need from a static site host and has
a comprehensive, well-documented toolchain. Seriously, what am I missing?
Would DO be better under peak loads or something?

~~~
akvadrako
No, it's just that Netlify is proprietary and only works for static sites. The
method in this article is more general.

For this use-case Netlify is the better option.

~~~
tomcam
Thanks much. I really was trying to learn, downvotes to the contrary.

------
wheresvic1
While this is pretty cool, it's also not all that much of an effort to setup
https using certbot and have it automatically configure nginx:
[https://smalldata.tech/blog/2015/12/29/nginx-nodejs-and-
http...](https://smalldata.tech/blog/2015/12/29/nginx-nodejs-and-https-via-
letsencrypt)

Setting up the renew job is also a very simple cron job.

Moreover, something that one forgets is that once you have your posts,
comments and any sort of data, you need to have backups and other sysadminy
stuff.

Personally, I enjoyed learning about this while setting up my blog :)

------
catears
Perhaps a bit off-topic, but if you run a lighter blog and specifically want
to do it on a machine you control the I can recommend using the nginx:alpine
docker image to host your site. All you need to build it is a COPY command:

    
    
       COPY ./my_static_files /usr/share/nginx/html
    

This alone wont get you HTTPS, but I wouldn't be surprised if you can get that
working with little effort using docker volumes and certbot

------
jypepin
Once, I worked on a Rails app that was setup in a docker compose environment.
I won't talk about prod, but was very surprised to see how much more complex
it made developing locally, having to deal with docker instances and such,
compared to just run `rails s` if we weren't using Docker.

Was the app setup improperly, or is that expected that using Docker will make
local development more complex?

~~~
likeclockwork
It's a mixed bag. Some of it was probably improper setup. With mounts and
docker exec and such it's easy to go into the container and rails s or rails
console and do what you need to do. But you have to deal with user permissions
if your app creates files and some other things but you can just use a docker
container as a very lightweight VM.

On the other side you have to track down and figure out how to install or
build whatever obscure old Ruby version they're using and dirty your machine
installing and running services to support the app. All of which is also
painful.

I do client work and I'd rather not dirty my machine installing old or random
software to work on a project. So having portable local environments works
well for me. But they do take some thought to set up and people often don't
take enough care in either case to document the procedure for getting things
set up to work on it.

------
apatters
Like, why?

Am I being too cheeky if I point out that setting up a droplet with a
WordPress blog on DigitalOcean takes three minutes? :)

(They have a premade image for it)

------
hardwaresofton
The most efficient host-your-own-blog I've ever seen is just static blog
generation & S3. I don't do it myself (ironically, I run tiny kubernetes
cluster and in the past had a systemd-managed docker+ngin+LE setup before
that) but it doesn't get much simpler than uploading a folder to S3 that's
being served by amazon as a website.

------
eclipsetheworld
More people should know about Caddy. A webserver with built-in HTTPS. We've
been using it in production and the experience has been great so far:
[https://caddyserver.com/](https://caddyserver.com/)

~~~
steve19
Using caddy for anything that might be commercial,by compiling, seems like a
huge pain:

[https://www.digitalocean.com/community/tutorials/how-to-
host...](https://www.digitalocean.com/community/tutorials/how-to-host-a-
website-with-caddy-on-ubuntu-16-04)

~~~
eclipsetheworld
The Caddy license page states that:

 _" If your company uses official Caddy binaries internally, in production, or
distributes Caddy, a commercial license is required."_

So if you are not using the official binaries (for example a community-
provided Caddy Docker image) a commercial license is not required.

------
qrbLPHiKpiux
I really miss the days when plain text files were used on a simple apache
server linked with simple html pages. We've gone from concentrating on content
to concentrating on the visuals, first.

------
ducaale
or you can just use [https://github.com/SteveLTN/https-
portal](https://github.com/SteveLTN/https-portal) for ssl termination

------
Dowwie
How about not using any of that and instead using one of the hundred static
site generators on GitHub and github.io hosting?

~~~
tokyodude
it's twice as expensive? $120 a year vs $60? (unless you make your content
open source in which case github is free)

~~~
wheresvic1
Gitlab also provides hosting and free private repos.

------
biggio
I want FTP back!

~~~
comtn
SFTP?

------
zellux
I've been using Netlify for a while with Hugo as site generator. It's free
with HTTPS and CDN support.

------
techaddict009
Why do you guys love complexing so much? Why not use one click wp instance
from DO images?

~~~
hannasanarion
Because it's fun

------
alphabettsy
Hugo + Netlify is simpler and faster. Just saying.

------
opmac
GitHub pages with HTTPS support is easier :P

------
pbreit
Would this work OK in 512mb at, say, Vultr?

~~~
xxdesmus
As long as you have some swap configured you’ll probably be fine.

~~~
peterwwillis
Alternately, generate static HTML, run a bare web server and use about 16MB of
RAM.

~~~
tathougies
Why even bother running a web server? Just use S3 with cloudfront.

~~~
peterwwillis
It looks like this would work, but you would have to use www.myblog.com
instead of myblog.com since you have to use a CNAME to use cloudfront. Maybe
using cloudflare's CNAME flattening?

~~~
krallja
Unless you host your domain servers on Route53, in which case you can
configure an alias record at the apex.

------
coleifer
Premature optimization something something...and honestly this isn't even
optimization, just some extra complexity.

Dockers cool for doing dev stuff on your laptop, or for scaling out with
something like kubernetes. This is just silly!

------
hidiegomariani
use medium

~~~
Sohcahtoa82
This was already proposed and shot down for various reasons:
[https://news.ycombinator.com/item?id=17983366](https://news.ycombinator.com/item?id=17983366)

------
instaheat
I'm just curious - why? Forgive me if I am missing the obvious advantage over
a blogging platform like medium.

~~~
Kpourdeilami
Medium's reading experience is pretty bad with all the annoying popups showing
up all over the place. Also with Ghost you can easily export your data and
move it across different ghost installations, you can customize the look and
feel of the blog, you can use your own custom domain without paying medium
extra for that, etc.

~~~
ageitgey
For anyone that wants to move from Medium to Ghost easily, I made this thing
to do that:
[https://github.com/ageitgey/medium_to_ghost](https://github.com/ageitgey/medium_to_ghost)

~~~
jazzyjackson
Ghost uses markdown, right? So does this tool export my medium blogs as
markdown files, with links to the image files already embedded?

If so, I will be forever indebted xD

~~~
ageitgey
Ghost 2.0 uses Mobiledoc format now. But you could get Markdown + Images out
of this with a little hacking and passing the output to
[https://github.com/yuloh/mobiledoc-markdown-
renderer](https://github.com/yuloh/mobiledoc-markdown-renderer)

------
fapjacks
This does not belong on HN at all. 1) It is not novel or interesting and 2) it
is made worse through being self-promotion. Do not make posts like this.

Edited to add: But to scratch the stupid itch I tried hard not to scratch and
respond to the other people here, I do this with my own personal blog and it's
totally fine. All of my self-hosted software is containerized behind an HTTP
reverse proxy. I can do it any number of ways but "Rely on <external third-
party service>" seems like a terrible idea to me. And there is _no reason
whatsoever_ for all the posts in this thread naysaying this particular way of
doing it, any more than there's any particular reason to naysay the suggested
alternatives. Do whatever you want. Learn something. Improve your skillset.

~~~
benatkin
Read the HN rules. People are allowed to submit their own content. By the way,
your username appears to promote a disgusting slang term. How is that any
better?

~~~
fapjacks
There were two whole qualifiers in my statement, half of which you ignored.
Self-promotion is obviously okay. However self-promotion of bland, boring
posts that regurgitate nearly useless information which has been posted
hundreds of times... Edit: Oh, I see that you have a long history of twisting
the words of others and personally attacking those you disagree with, so we're
done here. You have a nice evening.

