Linux VM¶
This guide shows how to self-host xlwings Lite on a plain Linux VM using the xlwings-lite CLI.
Prerequisites¶
A Linux VM (e.g., Ubuntu 24.04 LTS). Recommended minimal specs: 1 vCPU, 1 GB RAM, 25 GB SSD.
A hostname pointing to the Linux VM, e.g.,
xlwings-lite.mycompany.com.Docker installed on the VM:
curl -fsSL https://get.docker.com -o get-docker.sh sudo sh ./get-docker.sh
If this doesn’t work, follow Docker’s official installation guide.
bzip2installed on the VM:Ubuntu/Debian:
sudo apt install -y bzip2RHEL/Fedora/Amazon Linux:
sudo dnf install -y bzip2
An xlwings license key. If you don’t have one, you can request a trial key.
Install¶
1. Provide TLS certificates¶
xlwings Lite is an Office.js add-in, which requires TLS certificates even when hosted internally. xlwings Lite expects your cert and key under /etc/xlwings-lite/certs/, named tls.crt and tls.key.
If you need help with creating the certificates, see here:
2. Install the xlwings-lite CLI¶
sudo curl -fsSL https://lite.xlwings.org/cli -o /usr/local/bin/xlwings-lite
sudo chmod +x /usr/local/bin/xlwings-lite
3. Run the installer¶
sudo xlwings-lite install
Once install prints Running, visit https://<your-hostname> in your browser to confirm (the page shows the version of xlwings Lite).
4. Register the add-in with Microsoft 365 admin center¶
In your browser, go to
https://<your-hostname>/manifest, which will downloadxlwings-lite-manifest.xml.Go to Microsoft 365 admin center
Click on
Show all>Settings>Integrated Apps.If you have xlwings Lite installed, uninstall it first.
Click on
Upload custom appsand selectOffice Add-in(App type).Select
Upload manifest file (.xml) from device. ClickChoose File, then select thexlwings-lite-manifest.xmlfrom the previous step.Click
Next, then assign the desired users.Click
Nextand accept permission requests.Click
NextandFinish deployment.
The users will get the add-in to show up automatically although it may take a few hours.
5. Download Pyodide (for production)¶
The xlwings Lite container ships with only the default version of the Pyodide distribution. When you upgrade the container, that version may change — and any workbook pinned to a previous Pyodide version will need to upgrade to the new Pyodide version.
To prevent this, download the desired Pyodide versions locally on the VM. The CLI fetches the official release from GitHub, extracts it, and bind-mounts it into the container automatically. Currently supported versions are:
0.27.5
To download one or more versions:
sudo xlwings-lite pyodide download -v 0.27.5
Pass -v (or --version) once per Pyodide version.
Files are stored under /var/lib/xlwings-lite/pyodide/v<version>/. If xlwings Lite is already running, the CLI restarts the container automatically so the new versions are served immediately. Note that each Pyodide release requires around 500 MB of storage.
Maintenance¶
Update xlwings Lite¶
To update xlwings Lite to the latest version, run:
sudo xlwings-lite update
Update the xlwings-lite CLI¶
To update the CLI, simply re-run the install command:
sudo curl -fsSL https://lite.xlwings.org/cli -o /usr/local/bin/xlwings-lite
sudo chmod +x /usr/local/bin/xlwings-lite
Edit the configuration¶
The config file is /etc/xlwings-lite/xlwings-lite.conf. After editing, run sudo xlwings-lite restart to apply. See Environment variables for the full list of supported settings.
Uninstall¶
sudo xlwings-lite stop
sudo rm /usr/local/bin/xlwings-lite
sudo rm -rf /etc/xlwings-lite /var/lib/xlwings-lite
You may also want to remove Docker and the Docker images.
Note
If you want to remove the add-in again and run into issues (“Remove apps failed. No apps were successfully removed. Please try to remove them later.”), use this legacy URL: https://admin.microsoft.com/#/Settings/AddIns
TLS certificates via Windows CA Server¶
If you issue your TLS certificates from a Windows CA Server (i.e., Active Directory Certificate Services / AD CS), here’s how to obtain one for your Linux VM. Steps marked (Linux) are run on the Linux VM (e.g., via PuTTY); steps marked (Windows CA) are run on the Windows CA server in a command prompt with admin rights.
(Linux) Change into the certs folder:
mkdir -p /etc/xlwings-lite/certs cd /etc/xlwings-lite/certs
(Linux) Create a config file. Make sure to replace
<your-vm.example.com>in both places with your own domain name:cat > csr.cnf <<'EOF' [req] distinguished_name = req_distinguished_name req_extensions = v3_req prompt = no [req_distinguished_name] CN = <your-vm.example.com> [v3_req] subjectAltName = @alt_names [alt_names] DNS.1 = <your-vm.example.com> EOF
(Linux) Create the CSR file:
openssl req -new -key tls.key -out tls.csr -config csr.cnf
Copy
/etc/xlwings-lite/certs/tls.csrfrom the Linux VM to the Windows CA server, e.g., using WinSCP.(Windows CA) Generate the leaf certificate:
certreq -submit -attrib "CertificateTemplate:WebServer" tls.csr tls.leaf.crt
(Windows CA) Export the issuing CA certificate:
certutil -ca.cert ca.crt
This exports the certificate of the CA that signed your leaf cert, which you’ll need in the next step to complete the chain.
Copy
tls.leaf.crtandca.crtback to the Linux VM (e.g., using WinSCP). Copy them to/tmp/first to avoid any permission errors, then move them into place:sudo mv /tmp/tls.leaf.crt /tmp/ca.crt /etc/xlwings-lite/certs
(Linux) Build the fullchain certificate that the app will actually serve:
cd /etc/xlwings-lite/certs cat tls.leaf.crt ca.crt > tls.crt
Note
In a 2-tier (or deeper) AD CS setup, the CA that signed your leaf cert is an intermediate CA whose own certificate is signed by an offline root CA. In that case
ca.crt(the intermediate) alone is not enough as clients need the full chain from leaf to root. Concatenate all certs in order from leaf to root:cat tls.leaf.crt intermediate.crt root.crt > tls.crt
To check what’s currently in your chain, run
openssl crl2pkcs7 -nocrl -certfile tls.crt | openssl pkcs7 -print_certs -nooutand verify eachsubjectmatches the next cert’sissuer. To obtain the root cert, ask your Windows admin or, on the CA server, opencertlm.msc→ Trusted Root Certification Authorities → Certificates, then export the relevant root as a Base-64 encoded.cerfile.(Linux) Set file permissions:
chmod 644 /etc/xlwings-lite/certs/tls.crt chmod 600 /etc/xlwings-lite/certs/tls.key
(Linux) Restart xlwings Lite:
xlwings-lite restartOpen
https://your-vm.example.comin a browser. The address bar should show the padlock with no warning.
Once it works, keep the tls.csr and config files around for the next renewal. When the cert expires (typically 1–2 years), you’ll regenerate the CSR and request a new leaf certificate. tls.key can be reused indefinitely or rotated.
TLS certificates via Let’s Encrypt (certbot)¶
If your VM’s hostname is a subdomain of a public domain you control (e.g. your-vm.example.com), you can get a free, auto-renewing certificate from Let’s Encrypt—even when the VM itself is not reachable from the public internet. Use the DNS-01 challenge, which proves domain ownership by creating a TXT record at _acme-challenge.your-vm.example.com instead of requiring inbound HTTP access.
With a DNS provider plugin (e.g. certbot-dns-cloudflare), renewals can be fully automated:
sudo certbot certonly \
--dns-cloudflare \
--dns-cloudflare-credentials ~/.secrets/cloudflare.ini \
-d your-vm.example.com
The certificate and key will be placed under /etc/letsencrypt/live/your-vm.example.com/ as fullchain.pem and privkey.pem. Since xlwings Lite reads the cert from /etc/xlwings-lite/certs/, add a deploy hook that copies the renewed files into place and restarts the service:
sudo mkdir -p /etc/letsencrypt/renewal-hooks/deploy
sudo tee /etc/letsencrypt/renewal-hooks/deploy/xlwings-lite.sh > /dev/null <<'EOF'
#!/bin/bash
set -e
cp /etc/letsencrypt/live/your-vm.example.com/fullchain.pem /etc/xlwings-lite/certs/tls.crt
cp /etc/letsencrypt/live/your-vm.example.com/privkey.pem /etc/xlwings-lite/certs/tls.key
chmod 644 /etc/xlwings-lite/certs/tls.crt
chmod 600 /etc/xlwings-lite/certs/tls.key
xlwings-lite restart
EOF
sudo chmod +x /etc/letsencrypt/renewal-hooks/deploy/xlwings-lite.sh
certbot’s systemd timer will then handle renewals automatically and run the hook each time the certificate is renewed.
Troubleshooting¶
cannot talk to the docker daemon— Start Docker:sudo systemctl start docker.