docs/documentation/platform/pki/applications/certificate-syncs/linux-server.mdx
import PostSyncCommandPlaceholders from "/snippets/documentation/platform/pki/applications/certificate-syncs/post-sync-command-placeholders.mdx";
Deploy certificates from Infisical to a directory on a Linux server over SSH. Files are written atomically over SFTP so a reader never sees a partially written certificate or key.
<Info> Certificate Syncs are configured per Application. First select which certificates to sync, then configure the Linux Server destination. </Info> 2. Select the **Linux Server** option.
3. Configure the **Destination**:
- **SSH Connection**: The SSH Connection used to reach the server.
- **Destination Directory**: The absolute path to the directory where certificate files are written, for example `/etc/ssl/certs`.
4. Configure the **Sync Options**:
- **Export Format**: Choose **PEM** to write separate certificate, chain, and key files, or **PKCS#12** to write a single password-protected `.pfx` bundle.
- **Certificate File Extension**: For PEM, choose `.pem` (default) or `.crt` for the certificate and chain files. Both hold the same PEM-encoded content, so pick the one the consuming service expects.
- **Combine Certificate and Chain**: For PEM, write the leaf certificate followed by the chain in a single file (a full-chain file, as nginx expects) and skip the separate chain file.
- **File Permissions** and **Private Key Permissions**: Octal modes for the delivered certificate and chain files (default `644`) and for the private key file (default `600`).
- **Owner** and **Group**: Optionally set the owner and group on the delivered files. Changing ownership requires the connection user to be root or to have passwordless sudo.
- **PKCS#12 Password**: Required when the export format is PKCS#12. It protects the delivered bundle.
- **Include Private Key**: For PEM, controls whether the private key is written alongside the certificate. The sync fails for a certificate whose key is not available, for example one issued from an external CSR.
- **Include Root CA in Certificate Chain**: Include the root CA in the delivered chain. Leave it off when the consuming service only needs the intermediates.
- **Enable Removal of Certificates**: Delete the delivered files from the server when a certificate is removed from the sync, revoked, or expired.
- **Certificate Name Schema**: The base file name, using placeholders such as `{{commonName}}`, `{{certificateId}}`, or `{{shortCertificateId}}`. The export format adds the extension. A schema with no placeholder can be linked to only one certificate.
- **Auto-Sync Enabled**: Automatically sync certificates when changes occur.
5. Configure the **Post-Sync Command**, or leave it empty:
- **Command**: A command run on the server after the sync delivers a certificate, so the service that uses it picks up the new file, for example `sudo systemctl reload nginx`. [Post-Sync Commands](#post-sync-commands) covers the available placeholders and what happens when the command fails.
6. Configure the **Details**:
- **Name**: The name of your sync.
- **Description**: Optional description.
7. Select which certificates should be synced.
8. Review and click **Create Sync**.
</Tab>
<Tab title="API">
To create a **Linux Server Certificate Sync**, make an API request to the [Create Linux Server PKI Sync](/api-reference/endpoints/pki/syncs/linux-server/create) endpoint.
### Sample request
```bash Request
curl --request POST \
--url https://app.infisical.com/api/v1/cert-manager/syncs/linux-server \
--header 'Authorization: Bearer <access-token>' \
--header 'Content-Type: application/json' \
--data '{
"name": "my-linux-cert-sync",
"applicationId": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
"connectionId": "550e8400-e29b-41d4-a716-446655440000",
"isAutoSyncEnabled": true,
"certificateIds": ["550e8400-e29b-41d4-a716-446655440000"],
"syncOptions": {
"exportFormat": "pem",
"includePrivateKey": true,
"canRemoveCertificates": true,
"certificateNameSchema": "{{commonName}}",
"postSyncCommand": "sudo systemctl reload nginx"
},
"destinationConfig": {
"destinationPath": "/etc/ssl/certs"
}
}'
```
</Tab>
The file extension is set by the export format, not by the name schema. The name schema only provides the base file name.
PEM writes the certificate, chain, and private key (when included) as separate files. The certificate and chain files use the extension you select, either .pem (default) or .crt.
PKCS#12 writes a single password-protected .pfx bundle that contains the certificate, chain, and private key.
For a certificate whose common name is app.example.com, synced to /etc/ssl/certs with the default {{commonName}} name schema, the delivered files are:
PEM (.pem extension)
/etc/ssl/certs/app.example.com.pem certificate
/etc/ssl/certs/app.example.com.chain.pem chain
/etc/ssl/certs/app.example.com.key private key (when included)
PKCS#12
/etc/ssl/certs/app.example.com.pfx
When syncing certificates, Infisical opens an SSH session to the server and, for each certificate, packages it in the chosen export format and writes the resulting files to the destination directory. Files are written atomically over SFTP so a reader never sees a partially written certificate or key.
Delivering a certificate file does not make the service use it. Nginx keeps serving the old certificate until something reloads it. A post-sync command is that last step, run for you right after the files land.
Set one command on the sync. It runs on the target server, in that server's own shell, once per sync run that delivers at least one file. Leaving the field empty means nothing runs, so there is no separate toggle. If a sync run does not complete, Infisical may attempt it again and the command runs with it, so prefer a command that is safe to run more than once.
The field accepts a whole script, so several steps can run in one go: put each on its own line, or chain them with &&.
The command runs on the target server, not on Infisical, and only after the whole delivery has finished:
sequenceDiagram
participant I as Infisical
participant G as Gateway
participant S as Target server
I->>G: Deliver certificate files
G->>S: Write files
G->>S: Remove files for certificates no longer synced
Note over G,S: Only once the server is in its final state
I->>G: Run the post-sync command
G->>S: Execute as the connection's account
S-->>G: Output and outcome
G-->>I: Success, or the reason it failed
```bash
cp {{certificatePath}} /etc/nginx/ssl/live.pem && systemctl reload nginx
```
A command is limited to 2048 characters, counted after the placeholders are substituted. For anything longer, put the logic in a script on the server and call that script.
By default the shell only reports the **last** line's exit status, so an earlier line that fails is not noticed and the sync still reports success. Start the script with `set -e` so the first failure stops it and fails the sync:
```bash
set -e
cp {{certificatePath}} /etc/nginx/ssl/live.pem
nginx -t
systemctl reload nginx
```
The command runs as the account the SSH Connection authenticates with, so constraining that account bounds what any command can do. A service reload does not need root. Grant the connection user a sudoers rule for that one command instead:
svc-infisical ALL=(root) NOPASSWD: /usr/bin/systemctl reload nginx
Anyone who can edit the sync can change the command, so treat edit access to these syncs as access to the target server.
<Warning> The rendered command is visible in the target server's process table while it runs. This only matters if you reference `{{pkcs12Password}}`, and only to accounts that already have a shell on the server the sync writes private keys to. </Warning>When certificate removal is enabled and a certificate is removed from the sync, revoked, or expired, Infisical deletes exactly the files it delivered for that certificate.