This is an nginx configuration of a reverse proxy to an S3-compatible backend, such as AWS S3 itself, Minio or Wasabi.
It can function as an HTTP(S) caching node, typically useful for serving static web sites.
It compiles nginx from source adding ngx_aws_auth and ngx_headers_more modules, and enables some useful built-in ones. Take a look at the Dockerfile.
- Clone this repo. Read, confirm or tweak the opinionated settings in
make image
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:
export VERSION=$(date +'%Y%m%d_%H%M%S'); make image
- To run a container, first create a
secrets.env
file in the repo root directory with the contents:
NGINX_S3_SERVER_NAME=<your server name, e.g. example.com>
NGINX_S3_PROXY_URL=<URL of the S3 server, see examples below>
NGINX_S3_ACCESS_KEY=<e.g. 1AMZ56N0NL6X032ZMLW7>
NGINX_S3_SECRET_KEY=<e.g. Ig1SxVgistQ4W3nwwG0CsFy6l9ua485o9rh0fxGY>
NGINX_S3_BUCKET=<your S3 bucket name>
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/
.
- Then run a container with:
make DEBUG=1 run NAME=<your server name>
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:
sudo -E make ENV=prod run NAME=<your server name>
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.
There’s basic support for automating renewals of TLS certificates using Let’s Encrypt and acme-tiny.
- First build the
*-letsencrypt
image variant:
make LETSENCRYPT=1 image
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.
- Ensure that the existing container serving on
:80
and:443
is stopped:
sudo podman stop <your server name>
- Run the
*-letsencrypt
image variant:
sudo -E make DEBUG=1 LETSENCRYPT=1 ENV=prod run NAME=tls-renew
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.
- Run the TLS renewal script:
sudo podman exec -it tls-renew ./renew-tls-cert.sh <your server name>
If everything goes well, you should see some acme-tiny
output and the
last two lines should be:
Signing certificate...
Certificate signed!
- 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 <your server name>
or recreate it
with sudo -E make ENV=prod run NAME=<your server name>
.