├── install.sh
├── README.md
└── renew.acme.sh
/install.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 |
3 | mkdir -p /config/.acme.sh /config/scripts
4 | curl -o /config/.acme.sh/acme.sh https://raw.githubusercontent.com/acmesh-official/acme.sh/master/acme.sh
5 | curl -o /config/scripts/renew.acme.sh https://raw.githubusercontent.com/j-c-m/ubnt-letsencrypt/master/renew.acme.sh
6 | chmod 755 /config/.acme.sh/acme.sh /config/scripts/renew.acme.sh
7 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Let's Encrypt with the Ubiquiti EdgeRouter
2 |
3 | This guide uses and
4 | to generate a valid SSL certificate for the EdgeRouter.
5 |
6 | * Does not ever expose the admin GUI to the internet
7 | * 100% /config driven, does not require modification to EdgeOS system files
8 |
9 | ## Install acme.sh & scripts
10 |
11 | * Connect via ssh to your EdgeRouter and execute the following command.
12 | ```
13 | curl https://raw.githubusercontent.com/zen/ubnt-letsencrypt/master/install.sh | sudo bash
14 | ```
15 |
16 | ## Configuration
17 |
18 | * In the steps below replace/verify the following:
19 | * subdomain.example.com - FQDN
20 | * 192.168.1.1 - LAN IP of Router
21 | * Configure DNS record for subdomain.example.com to your public WAN IP.
22 | * Connect via ssh to your EdgeRouter.
23 |
24 | 1. Initialize your certificate.
25 |
26 | ```
27 | sudo /config/scripts/renew.acme.sh -d subdomain.example.com
28 | ```
29 |
30 | You can include additional common names for your certificate, so long as they resolve to the same WAN address:
31 |
32 | ```
33 | sudo /config/scripts/renew.acme.sh -d subdomain.example.com -d subdomain2.example.com
34 | ```
35 |
36 | 2. Enter configuration mode.
37 |
38 | ```
39 | configure
40 | ```
41 |
42 | 3. Setup static host mapping for FQDN to the LAN IP.
43 |
44 | ```
45 | set system static-host-mapping host-name subdomain.example.com inet 192.168.1.1
46 | ```
47 |
48 | 4. Configure cert-file location for gui.
49 |
50 | ```
51 | set service gui cert-file /config/ssl/server.pem
52 | set service gui ca-file /config/ssl/ca.pem
53 | ```
54 |
55 | 5. Configure task scheduler to renew certificate automatically.
56 |
57 | ```
58 | set system task-scheduler task renew.acme executable path /config/scripts/renew.acme.sh
59 | set system task-scheduler task renew.acme interval 1d
60 | set system task-scheduler task renew.acme executable arguments '-d subdomain.example.com'
61 | ```
62 |
63 | If you included multiple names in step 1, you'll need to include any additional names here as well.
64 |
65 | ```
66 | set system task-scheduler task renew.acme executable arguments '-d subdomain.example.com -d subdomain2.example.com'
67 | ```
68 |
69 | 6. Commit, save and exit configuration mode.
70 |
71 | ```
72 | commit
73 | save
74 | exit
75 | ```
76 |
77 |
78 | 7. Accesss your router by going to
79 |
80 | ## Changelog
81 |
82 | 20220624 - Update acme.sh repo to https://github.com/acmesh-official/acme.sh
83 | 20210622 - Update option handling to pass --debug and --force to acme.sh
84 | 20210621 - Default to Let's Encrypt CA
85 | - Add -f to force renew
86 | 20200419 - Use SIGTERM for GUI service stop
87 | 20200109 - Use systemctl on 2.0 to start GUI service
88 | 20191022 - Prevent sudo error
89 | 20190311 - Initialize certificate first outside of configuration mode
90 | 20180609 - Install script
91 | 20180605 - IPv6 support
92 | 20180213 - Deprecate -i option
93 | 20171126 - Add ca.pem for complete certificate chain
94 | - Temporarily disable http port forwarding during renew
95 | 20171013 - Remove reload.acme.sh
96 | 20170530 - Check wan ip
97 | 20170417 - Stop gui service during challenge
98 | 20170320 - Add multiple name support
99 | 20170317 - Change from standalone to webroot auth using lighttpd
100 | 20170224 - Bug fixes
101 | 20170110 - Born
102 |
--------------------------------------------------------------------------------
/renew.acme.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 |
3 | usage() {
4 | echo "Usage: $0 -d [-d ] [options ...]
5 | Options:
6 | -h, --help Show this help message.
7 | -d, --domain Specifies domain for cert, allowed multiple times.
8 | -f, --force Force cert renewal.
9 | --debug [0|1|2|3] Output debug info. Defaults to 1 if argument is omitted.
10 | " 1>&2; exit 1;
11 | }
12 |
13 | kill_and_wait() {
14 | local pid=$1
15 | [ -z $pid ] && return
16 |
17 | kill $pid 2> /dev/null
18 | while kill -s 0 $pid 2> /dev/null; do
19 | sleep 1
20 | done
21 | }
22 |
23 | log() {
24 | if [ -z "$2" ]
25 | then
26 | printf -- "%s %s\n" "[$(date)]" "$1"
27 | fi
28 | }
29 |
30 | while [ ${#} -gt 0 ]; do
31 | case "${1}" in
32 | -h|--help)
33 | usage
34 | ;;
35 | -f|--force)
36 | FORCE="--force"
37 | ;;
38 | -i)
39 | shift
40 | ;;
41 | -d|--domain)
42 | if [ -z "$2" ] || [ "${2:0:1}" = "-" ]; then
43 | echo "Domain required"
44 | usage
45 | fi
46 | DOMAIN+=("$2")
47 | shift
48 | ;;
49 | --debug)
50 | if [ -z "$2" ] || [ "${2:0:1}" = "-" ]; then
51 | DEBUG="--debug 1"
52 | else
53 | DEBUG="--debug ${2}"
54 | shift
55 | fi
56 | ;;
57 | *)
58 | echo "Unknown parameter : ${1}"
59 | usage
60 | ;;
61 | esac
62 | shift 1
63 | done
64 |
65 | # check for required parameters
66 | if [ ${#DOMAIN[@]} -eq 0 ]; then
67 | echo "Domain required"
68 | usage
69 | fi
70 |
71 | # prepare our domain flags for acme.sh
72 | for val in "${DOMAIN[@]}"; do
73 | DOMAINARG+="-d $val "
74 | done
75 |
76 | ACMEHOME=/config/.acme.sh
77 |
78 | mkdir -p $ACMEHOME/webroot
79 |
80 | (
81 | cat <$ACMEHOME/lighttpd.conf
92 |
93 | log "Stopping GUI service."
94 | if [ -e "/var/run/lighttpd.pid" ]; then
95 | kill_and_wait $(cat /var/run/lighttpd.pid)
96 | fi
97 |
98 | log "Starting temporary ACME challenge service."
99 | /usr/sbin/lighttpd -f $ACMEHOME/lighttpd.conf
100 |
101 | /sbin/iptables -I INPUT 1 -p tcp -m comment --comment TEMP_LETSENCRYPT -m tcp --dport 80 -j ACCEPT
102 | /sbin/ip6tables -I INPUT 1 -p tcp -m comment --comment TEMP_LETSENCRYPT -m tcp --dport 80 -j ACCEPT
103 | /sbin/iptables -t nat -I PREROUTING 1 -p tcp -m comment --comment TEMP_LETSENCRYPT -m tcp --dport 80 -j ACCEPT
104 | mkdir -p /config/ssl
105 | # trick sudo detection in acme.sh
106 | unset SUDO_COMMAND
107 | $ACMEHOME/acme.sh --issue $DOMAINARG -w $ACMEHOME/webroot --home $ACMEHOME \
108 | --reloadcmd "cat $ACMEHOME/${DOMAIN[0]}/${DOMAIN[0]}.cer $ACMEHOME/${DOMAIN[0]}/${DOMAIN[0]}.key > /config/ssl/server.pem; cp $ACMEHOME/${DOMAIN[0]}/ca.cer /config/ssl/ca.pem" \
109 | --server letsencrypt ${FORCE} ${DEBUG}
110 | /sbin/iptables -D INPUT -p tcp -m comment --comment TEMP_LETSENCRYPT -m tcp --dport 80 -j ACCEPT
111 | /sbin/ip6tables -D INPUT -p tcp -m comment --comment TEMP_LETSENCRYPT -m tcp --dport 80 -j ACCEPT
112 | /sbin/iptables -t nat -D PREROUTING 1
113 |
114 | log "Stopping temporary ACME challenge service."
115 | if [ -e "$ACMEHOME/lighttpd.pid" ]; then
116 | kill_and_wait $(cat $ACMEHOME/lighttpd.pid)
117 | fi
118 |
119 | log "Starting GUI service."
120 | if [ -x "/bin/systemctl" ]; then
121 | /bin/systemctl start lighttpd.service
122 | else
123 | /usr/sbin/lighttpd -f /etc/lighttpd/lighttpd.conf
124 | fi
125 |
--------------------------------------------------------------------------------