https://github.com/filipnet/letsencrypt-transfer
Transfer LetsEncrypt certificates from one Linux server to another
https://github.com/filipnet/letsencrypt-transfer
bash bash-script certbot certificate certificates letsencrypt linux rsync script ssh transfer
Last synced: about 1 month ago
JSON representation
Transfer LetsEncrypt certificates from one Linux server to another
- Host: GitHub
- URL: https://github.com/filipnet/letsencrypt-transfer
- Owner: filipnet
- License: bsd-3-clause
- Created: 2020-11-20T07:52:08.000Z (over 5 years ago)
- Default Branch: main
- Last Pushed: 2021-10-27T04:40:46.000Z (over 4 years ago)
- Last Synced: 2024-12-27T08:16:11.422Z (over 1 year ago)
- Topics: bash, bash-script, certbot, certificate, certificates, letsencrypt, linux, rsync, script, ssh, transfer
- Language: Shell
- Homepage: https://www.filipnet.de
- Size: 1.95 KB
- Stars: 1
- Watchers: 1
- Forks: 0
- Open Issues: 0
-
Metadata Files:
- Readme: README.md
- License: LICENSE
Awesome Lists containing this project
README



# Let´s Encrypt Transfer
A robust Bash script to **securely transfer Let's Encrypt certificates** from one Linux server to another using SSH (pull method).
Ideal for setups with **load balancers**, **reverse proxies**, or **centralized certificate distribution**.
> ⚠️ **Important Notice**
> This script has been **fully refactored and modularized**.
> If you used a previous version, **you must now use `.conf` files inside `conf.d/`**. Direct parameter passing is no longer supported.
- [Let´s Encrypt Transfer](#lets-encrypt-transfer)
- [Features](#features)
- [Installation](#installation)
- [Directory Structure](#directory-structure)
- [Configuration](#configuration)
- [Multiple .conf files supported](#multiple-conf-files-supported)
- [Usage](#usage)
- [Testing First (Dry Run)](#testing-first-dry-run)
- [Automating (cronjob example)](#automating-cronjob-example)
- [Why use this script?](#why-use-this-script)
- [Requirements](#requirements)
- [Sample Output \& Logging](#sample-output--logging)
- [Security Considerations](#security-considerations)
- [Troubleshooting](#troubleshooting)
- [Contribution](#contribution)
- [License](#license)
## Features
- Transfers certificates (`archive`, `live`, `renewal`) over SSH using `rsync`
- Modular `.conf` based configuration (`conf.d/*.conf`)
- SSH key-based or password-based authentication
- Supports non-standard ports and SSH options
- Default dry-run mode (safe testing)
- Logging to file and stdout
- Post-transfer commands (e.g., reload services)
- Easily cronjob-able
## Installation
```bash
[ ! -d /opt ] && mkdir -p /opt && echo "Created /opt"
cd /opt
git clone https://github.com/filipnet/letsencrypt-transfer.git
cd letsencrypt-transfer
chmod +x letsencrypt-transfer.sh
```
## Directory Structure
```bash
letsencrypt-transfer/
├── letsencrypt-transfer.sh # Main script
├── conf.d/ # Directory for .conf definitions
│ └── example.conf # Copy & customize for each certificate set
└── .gitignore
```
## Configuration
Create one .conf file per certificate/domain in the conf.d/ directory.
Here is an example:
```ini
# === Basic Settings ===
SOURCE_HOST=web01.example.com
# Either use:
SSH_KEY=/root/.ssh/id_rsa_web01
# Or:
# SSH_USER=root
SSH_EXTRA_OPTS="-4 -p 2222"
RSYNC_EXTRA_OPTS="--compress --numeric-ids --recursive -az"
ARCHIVE_SOURCE=/etc/letsencrypt/archive/webmail.example.com/
ARCHIVE_DEST=/etc/letsencrypt/archive/webmail.example.com/
LIVE_SOURCE=/etc/letsencrypt/live/webmail.example.com/
LIVE_DEST=/etc/letsencrypt/live/webmail.example.com/
RENEWAL_SOURCE=/etc/letsencrypt/renewal/webmail.example.com.conf
RENEWAL_DEST=/etc/letsencrypt/renewal/webmail.example.com.conf
DRY_RUN=true
LOGGING_ENABLED=true
LOG_FILE=/var/log/letsencrypt-transfer.log
POST_COMMANDS=systemctl reload nginx,systemctl reload dovecot,systemctl reload postfix
```
## Multiple .conf files supported
The script will automatically process every file in conf.d/*.conf, skipping example.conf.
### Usage
```bash
./letsencrypt-transfer.sh
```
All matching .conf files in conf.d/ will be processed.
You will see output in stdout. If logging is enabled, a logfile is also written.
### Testing First (Dry Run)
By default, `DRY_RUN=true` in your .conf files.
This will show what would happen without modifying anything.
Set `DRY_RUN=false` in production.
### Automating (cronjob example)
Example cronjob that runs daily at 4:05 AM:
```cron
5 4 * * * /opt/letsencrypt-transfer/letsencrypt-transfer.sh >> /dev/null 2>&1
```
## Why use this script?
Let's Encrypt certificates are usually bound to a single machine for issuance (ACME challenge).
In setups with load balancers or multiple services, you need secure distribution of those certs — and that's exactly what this script does.
No Docker, no dependencies, just clean rsync and SSH.
## Requirements
- Bash
- SSH access to the source server
- rsync installed on both ends
- Let's Encrypt issued certs on source system
## Sample Output & Logging
All script actions are always printed to `stdout`, so you can directly follow what's happening — even when `DRY_RUN=true`.
If `ENABLE_LOGGING=true` is set in your config file, an additional logfile will be written to the specified `LOG_FILE` path.
This is useful for scheduled or automated runs (e.g., via cron).
When ENABLE_LOGGING=true, the same output will be saved to the path defined in LOG_FILE, e.g.: `/var/log/letsencrypt-transfer/mailserver.log`
## Security Considerations
This script transfers sensitive Let's Encrypt certificates over SSH.
Make sure only privileged users (e.g. `root`) execute the script, and that private keys and certificate files are stored securely with restrictive permissions (`chmod 600`).
Use SSH key-based authentication where possible, and limit access via firewall rules or SSH configuration.
Logging is minimal by design and does not include certificate contents.
Always test with `DRY_RUN=true` before enabling full sync in production environments.
Avoid exposing SSH directly to the public internet without proper hardening.
---
## Troubleshooting
If you encounter problems while using this tool (especially with SSH or rsync), please refer to the [HELP.md](./HELP.md) guide for solutions and best practices.
## Contribution
Contributions, ideas, improvements, and bug reports are always welcome!
Feel free to open a [Pull Request](https://github.com/filipnet/letsencrypt-transfer/pulls) or create an [Issue](https://github.com/filipnet/letsencrypt-transfer/issues)
to help improve this script for more users.
## License
**letsencrypt-transfer** and all individual scripts are released under the [BSD 3-Clause License](./LICENSE), unless explicitly noted otherwise.