Skip to content

Export letsencrypt certificates #683

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
dgeordgy21 opened this issue Nov 2, 2020 · 14 comments
Closed

Export letsencrypt certificates #683

dgeordgy21 opened this issue Nov 2, 2020 · 14 comments
Labels
enhancement v3 Considered for version 3

Comments

@dgeordgy21
Copy link

Hello,
Can you add a link to download each certificate generated by letsencrypt? It's usefull to put it in adguard for exemple DNS-over-TLS.
privkey.pem : the private key for your certificate.
fullchain.pem: the certificate file used in most server software.

Thes files are located in letsencrypt/live/npm-XX/

Thank you in advance.

@samborambo
Copy link

I would also like to be able to link to the cert folder based on the site name. Its useful for npm to handle renewal for certs for services other than web.

I can see where the numbered folders map to but having site name folders would ease configuration. Also concerned numbering may change, breaking cert paths.

@Salamafet
Copy link

Same here.

I use NPM on my Synology. I need to import the generate certificate for use it with Drive Client (desktop app).
The Drive App is not using a web protocol.

@nayefalebrahim
Copy link

nayefalebrahim commented Dec 13, 2020

First of all great project, really top-notch!

This feature would be helpful, as I'm using wildcard certs which I wish I could export from the UI.

Meanwhile, anyone using the docker image can copy the files from the container to the host with the following commands:

docker cp NPM_CONTAINER_ID:/etc/letsencrypt/archive/npm-X ./

Replace NPM_CONTAINER_ID with your container id, find it by running docker ps
Replace X with the order of the certificate, in my case I have one domain so it's 1

Example:
docker cp nginx_proxy_app_1:/etc/letsencrypt/archive/npm-1 ./

This will copy the certs from the container to the current working directory.

@cromulus
Copy link

If you have many sites and many ssl certs, it's difficult to discern which npm-[0-9]* folder contains the certificates you want.

I iterate through the nom folders and run openssl x509 -noout -subject -in cert.pem but it's sub-optimal.

@chaptergy
Copy link
Collaborator

Duplicate of #404

@Qaezar
Copy link

Qaezar commented Aug 12, 2021

+1, would love this too ! ;)

Thank you ^^

@samborambo
Copy link

samborambo commented Aug 12, 2021

I solved this with a python script to copy out the certs to named folders. Not very well tested.

https://pastebin.com/gfAu5X8B

@jc21 jc21 added the v3 Considered for version 3 label Aug 12, 2021
@marrobHD
Copy link

marrobHD commented Feb 13, 2022

I would also like to see this. I need to copy the SSL certificates over to mailcows SSL folder.
A better cert folder naming would be useful for building a script that does what I need.
Until now I'm turning off SSL on npm for the mailcow domains when the SSL certs run out. I run certbot on mailcows side and add ssl back to npm mailcow domains.

@captainabloc
Copy link

captainabloc commented Feb 26, 2022

Hi all,
here a small script for retrieving latest Fullchain and Privatekey from NPM.
Usefull for example for Adguardhome certificates renewal:

#!/bin/bash


# ----------------------------------
# Colors
# ----------------------------------
NOCOLOR='\033[0m'
RED='\033[0;31m'
GREEN='\033[0;32m'
ORANGE='\033[0;33m'
BLUE='\033[0;34m'
PURPLE='\033[0;35m'
CYAN='\033[0;36m'
LIGHTGRAY='\033[0;37m'
DARKGRAY='\033[1;30m'
LIGHTRED='\033[1;31m'
LIGHTGREEN='\033[1;32m'
YELLOW='\033[1;33m'
LIGHTBLUE='\033[1;34m'
LIGHTPURPLE='\033[1;35m'
LIGHTCYAN='\033[1;36m'
WHITE='\033[1;37m'

echo -e "${YELLOW}\n
1       abc.xyz
5       a.abc.xyz
6       b.abc.xyz
7       c.abc.xyz
8       d.abc.xyz
9       e.abc.xyz
10      f.abc.xyz
11      g.abc.xyz
12      h.abc.xyz
13      i.abc.xyz
14      j.abc.xyz
18      k.abc.xyz
19      l.abc.xyz
20      m.abc.xyz
22      n.abc.xyz
23      o.abc.xyz
30      p.abc.xyz
31      q.abc.xyz
32      r.abc.xyz
33      s.abc.xyz
34      t.abc.xyz
35      u.abc.xyz
36      v.abc.xyz
37      w.abc.xyz
38      x.abc.xyz
39      y.abc.xyz
49      z.abc.xyz\n\n${NOCOLOR}"

# Ask the user for the cert number
echo certificat number ?
read varname
echo -e "${BLUE} FULLCHAIN:\n\n"
cat "$(ls -rt /etc/letsencrypt/archive/npm-$varname/fullchain* | tail -n1)"
echo -e "${NOCOLOR}\n\n "
echo -e "\n ${GREEN} PRIVATE:\n\n"
cat "$(ls -rt /etc/letsencrypt/archive/npm-$varname/privkey* | tail -n1)"
echo -e "${NOCOLOR}\n\n "

certificates numbers found in /data/database.sqlite

hope this can be useful

@balya
Copy link

balya commented Jan 11, 2023

I use NPM on my Unaraid server.
Wrote a small script to transfer keys to another server with OPNsense. Perhaps someone will come in handy.
I run the script according to the schedule through the plugin User Scripts.

#!/usr/bin/python3
import os
from pathlib import Path
from paramiko import SSHClient
from scp import SCPClient
from paramiko import AutoAddPolicy, RSAKey, SSHClient

proxy_hosts_dir = '/mnt/user/appdata/Nginx-Proxy-Manager-Official/data/nginx/proxy_host'
archive_dir = '/mnt/user/appdata/Nginx-Proxy-Manager-Official/letsencrypt/archive'
target_host = 'dns.host'
host_file = ''

for filename in os.listdir(proxy_hosts_dir):
    file = os.path.join(proxy_hosts_dir, filename)
    if os.path.isfile(file) and filename.endswith('.conf'):
        with open(file) as f:
            if target_host in f.read():
                host_file = file

archive_id = int(Path(host_file).stem) + 1
archive_path = archive_dir + '/npm-' + str(archive_id)

max_cert = int(1)
for certfilename in os.listdir(archive_path):
    certfile = os.path.join(archive_path, certfilename)
    index = int(''.join(filter(lambda i: i.isdigit(), certfilename)))
    if index > max_cert:
        max_cert = index

fullchain = archive_path + '/fullchain' + str(max_cert) + '.pem'
privkey = archive_path + '/privkey' + str(max_cert) + '.pem'

client = SSHClient()
client.load_system_host_keys()
client.set_missing_host_key_policy(AutoAddPolicy())
client.connect('192.168.1.1', username='unraid')
sftp = client.open_sftp()
sftp.put(fullchain, '/home/unraid/letsencrypt/' + target_host + '.fullchain.pem')
sftp.put(privkey, '/home/unraid/letsencrypt/' + target_host + '.privkey.pem')
sftp.close()

@Moonbase59
Copy link

Moonbase59 commented Mar 29, 2023

@balya Thanks for your suggestion!

I run Prosody as a chat server (not on the NGINX Proxy Manager machine) and also need to transfer the certs to Prosody. I found the numbering scheme you use above not reliable, especially when making NPM configuration changes. So I opted for actually reading the relevant parts of NPM’s .conf files. (Excuse my bad Python…)

#!/usr/bin/python3
import re
import os
from pathlib import Path
from paramiko import SSHClient
from scp import SCPClient
from paramiko import AutoAddPolicy, RSAKey, SSHClient

proxy_hosts_dir = '/home/admin/npm/data/nginx/proxy_host'
archive_dir = '/home/admin/npm/letsencrypt/live'
target_host = 'chat.mydomain.net'
host_file = ''

for filename in os.listdir(proxy_hosts_dir):
    file = os.path.join(proxy_hosts_dir, filename)
    if os.path.isfile(file) and filename.endswith('.conf'):
        with open(file) as f:
            content = f.read();
            m = re.search(r'server_name\s+(.*);', content)
            if m:
              s = m.group(1).split()
              basename = ('_').join(s).replace("*", "x")
              if target_host in s:
                f = re.search(r'ssl_certificate\s+/etc/letsencrypt/live(.*);', content)
                if f:
                  fullchain = archive_dir + f.group(1)
                p = re.search(r'ssl_certificate_key\s+/etc/letsencrypt/live(.*);', content)
                if p:
                  privkey = archive_dir + p.group(1)

client = SSHClient()
client.load_system_host_keys()
client.set_missing_host_key_policy(AutoAddPolicy())
client.connect('prosody', username='myusername')
sftp = client.open_sftp()
sftp.put(fullchain, '/home/myusername/certs/' + target_host + '.fullchain.pem')
sftp.put(privkey, '/home/myusername/certs/' + target_host + '.privkey.pem')
sftp.close()

This script I run via root’s crontab on the NPM machine every night at 3:00 a.m. like so:

0 3 * * * /home/admin/bin/ssl-chat.py

And on the Prosody machine, since it can’t reload correctly, at 3:10 a.m., also via root’s crontab:

10 3 * * * prosodyctl --root cert import chat.mydomain.net /home/myusername/certs/

Works well so far. Maybe this can help others, too.

@smooth-baking-powder
Copy link

@balya Thanks for your suggestion!

I run Prosody as a chat server (not on the NGINX Proxy Manager machine) and also need to transfer the certs to Prosody. I found the numbering scheme you use above not reliable, especially when making NPM configuration changes. So I opted for actually reading the relevant parts of NPM’s .conf files. (Excuse my bad Python…)

#!/usr/bin/python3
import re
import os
from pathlib import Path
from paramiko import SSHClient
from scp import SCPClient
from paramiko import AutoAddPolicy, RSAKey, SSHClient

proxy_hosts_dir = '/home/admin/npm/data/nginx/proxy_host'
archive_dir = '/home/admin/npm/letsencrypt/live'
target_host = 'chat.mydomain.net'
host_file = ''

for filename in os.listdir(proxy_hosts_dir):
    file = os.path.join(proxy_hosts_dir, filename)
    if os.path.isfile(file) and filename.endswith('.conf'):
        with open(file) as f:
            content = f.read();
            m = re.search(r'server_name\s+(.*);', content)
            if m:
              s = m.group(1).split()
              basename = ('_').join(s).replace("*", "x")
              if target_host in s:
                f = re.search(r'ssl_certificate\s+/etc/letsencrypt/live(.*);', content)
                if f:
                  fullchain = archive_dir + f.group(1)
                p = re.search(r'ssl_certificate_key\s+/etc/letsencrypt/live(.*);', content)
                if p:
                  privkey = archive_dir + p.group(1)

client = SSHClient()
client.load_system_host_keys()
client.set_missing_host_key_policy(AutoAddPolicy())
client.connect('prosody', username='myusername')
sftp = client.open_sftp()
sftp.put(fullchain, '/home/myusername/certs/' + target_host + '.fullchain.pem')
sftp.put(privkey, '/home/myusername/certs/' + target_host + '.privkey.pem')
sftp.close()

This script I run via root’s crontab on the NPM machine every night at 3:00 a.m. like so:

0 3 * * * /home/admin/bin/ssl-chat.py

And on the Prosody machine, since it can’t reload correctly, at 3:10 a.m., also via root’s crontab:

10 3 * * * prosodyctl --root cert import chat.mydomain.net /home/myusername/certs/

Works well so far. Maybe this can help others, too.

If i use your script and edit the paths and username etc. i get this Error:
Traceback (most recent call last):
File "/root/./turn-ssl.sh", line 36, in
sftp.put(fullchain, '/opt/coturn/cert/' + target_host + '.fullchain.pem')
NameError: name 'fullchain' is not defined

No idea, how i can solve it

@LazyGatto
Copy link

I tried to write a sample script to export certificates from Nginx Proxy Manager for use with mailcow mail server. You can adapt it to use with any application. https://github.com/LazyGatto/npm-cert-export

@psychogun
Copy link

This is my take on it; one VM with NPM container (192.168.0.44)- another VM with a ZNC bouncer from where the bash script is run in a cron job from the root user, every 90 days. First execution is on the 25th of September 2023.

If you go to SSL Certificates in NPM, you can see which #number the certificate it is listed as (/home/yoyo/podman/npm/letsencrypt/live/npm-13) when you download it manually.

Cron:
crontab -e 0 0 25 9 */90 /root/fullchain_download.sh

I am running the ZNC bouncer as a regular user (wwhite) as a systems service (systemctl --user start container-znc.service) and I had some issues writing the files in to the shared directory with podman from that user. Therefore I opted to copy the root user's public key in to .ssh/authorized_keys on the yoyo user running NPM on the other machine.

#!/bin/bash


# Server details
SERVER_IP="192.168.0.44"
SSH_USER="yoyo"
REMOTE_DIR="/home/yoyo/podman/npm/letsencrypt/live/npm-13"

# Local directory
LOCAL_TMP="/home/wwhite/tmp"
LOCAL_ZNC="/home/wwhite/podman/znc"

# List of file names to download
FULLCHAIN="fullchain.pem"
PRIVKEY="privkey.pem"
FILES=("$FULLCHAIN" "$PRIVKEY")

echo "Attempting to connect to $SERVER_IP"

for FILE in "${FILES[@]}"; do
    scp "$SSH_USER@$SERVER_IP:$REMOTE_DIR/$FILE" "$LOCAL_TMP/"
    echo "$FILE downloaded to $LOCAL_TMP"
done

echo "Combining keys"
cat "$LOCAL_TMP/$PRIVKEY" > "$LOCAL_TMP/znc.pem"
cat "$LOCAL_TMP/$FULLCHAIN" >> "$LOCAL_TMP/znc.pem"

echo "Privkey and fullchain is combined to znc.pem"

mv "$LOCAL_TMP/znc.pem" "$LOCAL_ZNC"

echo "The combined znc.pem is moved in to the appropriate directory"

# Clean up process

rm $LOCAL_TMP/$FULLCHAIN
echo "Removed the temporary $FULLCHAIN"


rm $LOCAL_TMP/$PRIVKEY
echo "Removed the temporary $PRIVKEY"

chmod 0600 $LOCAL_ZNC/znc.pem
echo "Permission 0600 znc.pem"

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement v3 Considered for version 3
Projects
None yet
Development

No branches or pull requests