Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
114 changes: 114 additions & 0 deletions cf-nginx-letsencrypt/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,114 @@
# ColdFusion standalone application with Nginx and Let's Encrypt Certificate

This is a demonstration of Nginx used as a proxy for a ColdFusion 2021 application instance. The Nginx service uses a Let's Eencrypt certificate. The Nginx and Let's Encrypt configuration was adapted from [here](https://github.com/evgeniy-khist/letsencrypt-docker-compose).

## Initial Setup

### Prerequisites
1. Docker and Docker Compose are installed
2. You have a domain name
3. You have a server with a publicly routable IP address

### Step 1 - Edit config.env
Edit `DOMAIN` and `CERTBOT_EMAIL` to reflect the domain and email address to use.
To obtain a staging certificate from Lets Encrypt, set `CERTBOT_TEST_CERT=1`. Once comfortable the process works, change this to `0` to get a live (not staging) certificate.
The `acceptEULA` is for Coldfusion and may be left as is.
The `password` is the administrator account for Coldfusion.

[_config.env_](config.env)
```
DOMAIN=yourhostname.fqdn.com
[email protected]
CERTBOT_TEST_CERT=1
CERTBOT_RSA_KEY_SIZE=4096
acceptEULA=YES
password=CF123
```
### Step 2 - Create necessary Docker volumes
```bash
docker volume create --name=nginx_conf
docker volume create --name=letsencrypt_certs
```
### Step 3 - Build images and start containers

Build and run as daemon
```bash
docker compose up -d --build
```
After a bit (minute or two), you should be able to get to the following URLs:

1. Test Page [https://yourhostname.fqdn.com/test.cfm](https://yourhostname.fqdn.com/test.cfm)
2. Dump server Page [https://yourhostname.fqdn.com/dumpserver.cfm](https://yourhostname.fqdn.com/dumpserver.cfm)

The CF Admin page should be available on the system running the containers at this link: [http://localhost:8500/CFIDE/administrator/index.cfm](http://localhost:8500/CFIDE/administrator/index.cfm).

### Step 3.1
Check logs after containers are up
```bash
docker compose logs -f
```

### Step 4 - Stop
Stop the containers
```bash
docker compose down
```

## Get Production Lets Encrypt Cert

### Step 1 - Update config

Set `CERTBOT_TEST_CERT=0` in [`config.env`](config.env)

### Step 2 - Update docker containers
```bash
docker compose down
docker volume rm letsencrypt_certs
docker volume create --name=letsencrypt_certs
docker compose up -d
```

## Change Domain Name

### Step 1 - Update config

Change the domain name in [`config.env`](config.env)

### Step 2 - Update docker containers

```bash
docker compose down
docker volume rm nginx_conf
docker volume rm letsencrypt_certs
docker volume create --name=nginx_conf
docker volume create --name=letsencrypt_certs
docker compose up -d
```

## Docker Cleanup
Prune things [https://docs.docker.com/config/pruning/](https://docs.docker.com/config/pruning/)
```bash
docker image prune
docker container prune
docker volume prune
```

## Project structure
- [`docker-compose.yml`](docker-compose.yml)
- [`config.env`](config.env) - specifies domain name, email, and CF admin password
- [`app/`](app/) - mapped to app folder in coldfusion container
- [`dumpserver.cfm`](app/dumpserver.cfm)
- [`test.cfm`](app/test.cfm)
- [`certbot/`](certbot/)
- [`certbot.sh`](certbot/certbot.sh)
- [`Dockerfile`](certbot/Dockerfile)
- [`cron/`](cron/)
- [`Dockerfile`](cron/Dockerfile)
- [`renew_certs.sh`](cron/renew_certs.sh)
- [`nginx/`](nginx/)
- [`Dockerfile`](nginx/Dockerfile)
- [`gzip.conf`](nginx/gzip.conf)
- [`hsts.conf`](nginx/hsts.conf)
- [`nginx.sh`](nginx/nginx.sh)
- [`options-ssl-nginx.conf`](nginx/options-ssl-nginx.conf)
- [`site.conf.tpl`](nginx/site.conf.tpl) - Template file for nginx site
1 change: 1 addition & 0 deletions cf-nginx-letsencrypt/app/dumpserver.cfm
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
<cfdump var="#server.coldfusion#">
4 changes: 4 additions & 0 deletions cf-nginx-letsencrypt/app/test.cfm
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
<cfscript>
name="World"
writeoutput("Hello #name#! at #datetimeformat(now())#");
</cfscript>
9 changes: 9 additions & 0 deletions cf-nginx-letsencrypt/certbot/Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
FROM certbot/certbot:v1.29.0

RUN apk add --no-cache bash

COPY certbot.sh /opt/

RUN chmod +x /opt/certbot.sh

ENTRYPOINT ["/opt/certbot.sh"]
45 changes: 45 additions & 0 deletions cf-nginx-letsencrypt/certbot/certbot.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
#!/bin/bash

set -e

trap exit INT TERM

if [ -z "$DOMAIN" ]; then
echo "DOMAIN environment variable is not set"
exit 1;
fi

until nc -z nginx 80; do
echo "Waiting for nginx to start..."
sleep 5s & wait ${!}
done

if [ "$CERTBOT_TEST_CERT" != "0" ]; then
test_cert_arg="--test-cert"
fi

mkdir -p "/var/www/certbot/$DOMAIN"

if [ -d "/etc/letsencrypt/live/$DOMAIN" ]; then
echo "Let's Encrypt certificate for $DOMAIN already exists"
continue
fi

if [ -z "$EMAIL" ]; then
email_arg="--register-unsafely-without-email"
echo "Obtaining the certificate for $DOMAIN without email"
else
email_arg="--email $EMAIL"
echo "Obtaining the certificate for $DOMAIN with email $EMAIL"
fi

certbot certonly \
--webroot \
-w "/var/www/certbot/$DOMAIN" \
-d "$DOMAIN" \
$test_cert_arg \
$email_arg \
--rsa-key-size "${CERTBOT_RSA_KEY_SIZE:-4096}" \
--agree-tos \
--noninteractive \
--verbose || true
9 changes: 9 additions & 0 deletions cf-nginx-letsencrypt/coldfusion/Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
FROM adobecoldfusion/coldfusion2021:latest

#COPY *.xml /opt/coldfusion/config

WORKDIR /workdir

COPY coldfusion.sh /workdir

RUN chmod +x /workdir/coldfusion.sh
5 changes: 5 additions & 0 deletions cf-nginx-letsencrypt/coldfusion/coldfusion.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
#!/bin/sh

cd /workdir
echo "Additional ColdFusion container things would go here"
ls -al .
6 changes: 6 additions & 0 deletions cf-nginx-letsencrypt/config.env
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
DOMAIN=yourhostname.fqdn.com
[email protected]
CERTBOT_TEST_CERT=1
CERTBOT_RSA_KEY_SIZE=4096
acceptEULA=YES
password=CF123
12 changes: 12 additions & 0 deletions cf-nginx-letsencrypt/cron/Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
FROM alpine:3.16

RUN apk update && \
apk add --no-cache docker-cli docker-cli-compose

COPY renew_certs.sh /etc/periodic/daily/renew_certs

RUN chmod +x /etc/periodic/daily/renew_certs

WORKDIR /workdir

CMD ["crond", "-f", "-l", "0"]
7 changes: 7 additions & 0 deletions cf-nginx-letsencrypt/cron/renew_certs.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
#!/bin/sh

cd /workdir
echo "Renewing Let's Encrypt Certificates... (`date`)"
docker compose run --rm --no-TTY --entrypoint certbot certbot renew --no-random-sleep-on-renew
echo "Reloading Nginx configuration"
docker compose exec --no-TTY nginx nginx -s reload
57 changes: 57 additions & 0 deletions cf-nginx-letsencrypt/docker-compose.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
version: "3"

services:

coldfusion:
build: ./coldfusion
image: joeywas/coldfusion2021:latest
ports:
- "8500:8500"
env_file:
- ./config.env
volumes:
- ./app:/app
restart: unless-stopped

nginx:
build: ./nginx
image: joeywas/nginx:1.23-alpine
env_file:
- ./config.env
volumes:
- nginx_conf:/etc/nginx/sites
- letsencrypt_certs:/etc/letsencrypt
- certbot_acme_challenge:/var/www/certbot
- ./html:/var/www/html
depends_on:
- coldfusion
ports:
- "80:80"
- "443:443"
restart: unless-stopped

certbot:
build: ./certbot
image: joeywas/certbot:v1.29.0
env_file:
- ./config.env
volumes:
- letsencrypt_certs:/etc/letsencrypt
- certbot_acme_challenge:/var/www/certbot

cron:
build: ./cron
image: joeywas/cron
environment:
COMPOSE_PROJECT_NAME: "${COMPOSE_PROJECT_NAME}"
volumes:
- /var/run/docker.sock:/var/run/docker.sock
- ./:/workdir:ro
restart: unless-stopped

volumes:
nginx_conf:
external: true
letsencrypt_certs:
external: true
certbot_acme_challenge:
14 changes: 14 additions & 0 deletions cf-nginx-letsencrypt/nginx/Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
FROM nginx:1.23-alpine

RUN apk add --no-cache openssl

COPY nginx.conf /etc/nginx
COPY gzip.conf options-ssl-nginx.conf hsts.conf /etc/nginx/includes/
COPY site.conf.tpl /customization/
COPY nginx.sh /customization/

RUN chmod +x /customization/nginx.sh

EXPOSE 80

CMD ["/customization/nginx.sh"]
29 changes: 29 additions & 0 deletions cf-nginx-letsencrypt/nginx/gzip.conf
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
gzip on;
gzip_disable "msie6";

gzip_vary on;
gzip_proxied any;
gzip_comp_level 6;
gzip_buffers 16 8k;
gzip_http_version 1.1;
gzip_min_length 256;
gzip_types
application/atom+xml
application/geo+json
application/javascript
application/x-javascript
application/json
application/ld+json
application/manifest+json
application/rdf+xml
application/rss+xml
application/xhtml+xml
application/xml
font/eot
font/otf
font/ttf
image/svg+xml
text/css
text/javascript
text/plain
text/xml;
1 change: 1 addition & 0 deletions cf-nginx-letsencrypt/nginx/hsts.conf
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always;
14 changes: 14 additions & 0 deletions cf-nginx-letsencrypt/nginx/nginx.conf
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
user nginx;
worker_processes auto;

error_log /var/log/nginx/error.log notice;
pid /var/run/nginx.pid;

events {
worker_connections 1024;
}

http {
include /etc/nginx/includes/gzip.conf;
include /etc/nginx/sites/*.conf;
}
Loading