Ecosyste.ms: Awesome

An open API service indexing awesome lists of open source software.

Awesome Lists | Featured Topics | Projects

https://github.com/imiric/nginx-s3-proxy

A containerized nginx configuration of a reverse proxy to an S3-compatible backend. Simple serving of static websites.
https://github.com/imiric/nginx-s3-proxy

container docker nginx podman proxy s3

Last synced: 15 days ago
JSON representation

A containerized nginx configuration of a reverse proxy to an S3-compatible backend. Simple serving of static websites.

Awesome Lists containing this project

README

        

* nginx-s3-proxy

This is an nginx configuration of a reverse proxy to an S3-compatible
backend, such as [[https://aws.amazon.com/s3/][AWS S3]] itself, [[https://min.io/][Minio]] or [[https://wasabi.com/][Wasabi]].

It can function as an HTTP(S) caching node, typically useful for
serving static web sites.

It compiles nginx from source adding [[https://github.com/anomalizer/ngx_aws_auth][ngx_aws_auth]] and
[[https://github.com/openresty/headers-more-nginx-module][ngx_headers_more]] modules, and enables some useful built-in ones. Take
a look at the [[Dockerfile]].

** Usage

1. Clone this repo. Read, confirm or tweak the opinionated settings in
[[src/nginx.conf.tmpl]].

2. [@2] Install [[https://podman.io/][Podman]] (or directly use [[https://www.docker.com/][Docker]]
or another [[https://www.opencontainers.org/][OCI]]-compatible tool) and run:
#+BEGIN_SRC shell
make image
#+END_SRC

This should build a Podman image named ~imiric/nginx-s3-proxy~ and tagged
~latest~.

You can control the tag by setting the ~VERSION~ environment variable. For
example:
#+BEGIN_SRC shell
export VERSION=$(date +'%Y%m%d_%H%M%S'); make image
#+END_SRC

3. [@3] To run a container, first create a ~secrets.env~ file in the repo root
directory with the contents:
#+BEGIN_SRC shell
NGINX_S3_SERVER_NAME=
NGINX_S3_PROXY_URL=
NGINX_S3_ACCESS_KEY=
NGINX_S3_SECRET_KEY=
NGINX_S3_BUCKET=
#+END_SRC

~NGINX_S3_PROXY_URL~ for AWS S3 could be
~http://$BUCKET_NAME.s3-website-us-east-1.amazonaws.com/~, and for
Wasabi ~https://s3.us-east-1.wasabisys.com/$BUCKET_NAME/~.

4. [@4] Then run a container with:
#+BEGIN_SRC shell
make DEBUG=1 run NAME=
#+END_SRC

This should start the container in the foreground, mount the
~secrets.env~ file as a volume, generate the ~/etc/nginx/nginx.conf~ file,
and start ~nginx~ exposed to the host machine at ~127.0.0.1:8000~.

This is useful during development and testing, but in production run:
#+BEGIN_SRC shell
sudo -E make ENV=prod run NAME=
#+END_SRC

This should do as before, except run the container in the background
and also mount the ~/etc/ssl~ and ~/etc/letsencrypt~ host directories.

Root permission is needed for binding to ports <=1024, which this does
at ~0.0.0.0:80~ and ~0.0.0.0:443~.

~sudo -E~ is used to pass environment variables to the root ~podman~ process.
This is handy if you previously ran ~export VERSION=$(date +'%Y%m%d_%H%M%S')~
as all commands should build/use the same image version.

*** Renewing TLS certificate

There's basic support for automating renewals of TLS certificates using
[[https://letsencrypt.org/][Let's Encrypt]] and [[https://github.com/diafygi/acme-tiny][acme-tiny]].

1. First build the ~*-letsencrypt~ image variant:
#+BEGIN_SRC shell
make LETSENCRYPT=1 image
#+END_SRC

The reason a separate image is used for Let's Encrypt is to avoid bundling LE
dependencies in the production image, and to avoid exposing the
~/.well-known/acme-challenge/~ endpoint, which is only needed during renewal.

2. [@2] Ensure that the existing container serving on ~:80~ and ~:443~ is stopped:
#+BEGIN_SRC shell
sudo podman stop
#+END_SRC

3. [@3] Run the ~*-letsencrypt~ image variant:
#+BEGIN_SRC shell
sudo -E make DEBUG=1 LETSENCRYPT=1 ENV=prod run NAME=tls-renew
#+END_SRC

NOTE: We built the image in step 1 without ~sudo~ to reduce the amount
of damage a hostile build script could do, but the image won't be
available to ~root~ with this approach, and Podman will attempt to
fetch it from a public registry. If you trust the build process go
ahead and use ~sudo~ for building as well, but the author prefers to
build rootless, transfer the image to the production environment
via SSH and load it with ~cat image.tar | sudo podman load~.
In "proper" production you might want to push to a centralized
registry instead. Feel free to use the approach that best works for
you, but image deployment is out of scope for this project.

4. [@4] Run the TLS renewal script:
#+BEGIN_SRC shell
sudo podman exec -it tls-renew ./renew-tls-cert.sh
#+END_SRC

If everything goes well, you should see some ~acme-tiny~ output and the
last two lines should be:
#+BEGIN_SRC shell
Signing certificate...
Certificate signed!
#+END_SRC

5. [@5] Finally, exit the ~tls-renew~ container with Ctrl+C or
~sudo podman stop tls-renew~, and restart the original production
container with ~sudo podman restart ~ or recreate it
with ~sudo -E make ENV=prod run NAME=~.

** License

[[LICENSE][ISC]]