Why switch to self-hosted LimeSurvey
SaaS survey platforms charge per response, per seat, or per unlocked feature. That model works when volume is low and the team is small — it becomes costly as soon as an agency manages several clients at once, builds surveys with advanced conditional logic, or handles sensitive data (HR, health, market research). LimeSurvey Community Edition reverses this dynamic: the licence is GPL-2, the code is on GitHub, and an instance runs on any Linux VPS. You pay for infrastructure, not for usage. In return, you handle updates, backups and security — all of which this guide covers step by step.
What self-hosting actually changes
- Fixed, predictable cost — a single monthly VPS price covers all your projects, with no end-of-month surprises tied to response volume.
- Data under your control — your respondents' answers do not transit through a SaaS vendor's servers, which simplifies GDPR obligations towards your clients.
- No response cap — LimeSurvey Community Edition imposes no quota: you collect as many responses as your database can store.
- Full conditional logic — branching, regular expressions and equations are available in the community edition, with no upgrade required.
- Multi-client on a single instance — one installation lets you create separate user groups per client, each restricted to their own surveys.
- Open integrations — the LimeSurvey REST API and community plugins connect to your CRM, ERP or reporting tools at no connector cost.
- Updates on your schedule — you choose when to apply a new version, without being pushed through a forced migration mid-project.
Requirements: what you need before you start
LimeSurvey Community Edition is a standard PHP-MariaDB application. For resources, budget at least 1 vCPU and 2 GB of RAM for testing or a light load (a few surveys, a few hundred responses per day). For an agency with 5 to 10 active clients, a VPS with 2 vCPU and 4 GB of RAM is more appropriate — MariaDB grows its in-memory cache over time. Plan for 20 GB of disk: LimeSurvey stores survey media (images, files uploaded by respondents) in its data volume.
On the software side, you need Docker and Docker Compose installed, a domain or subdomain pointing to the VPS IP (e.g. surveys.your-domain.com), and ports 80 and 443 open in your firewall. Root or sudo SSH access to the machine is required for the installation.
Install LimeSurvey with Docker Compose, Nginx and HTTPS
Connect to the VPS and update the system
Open a terminal and connect via SSH:
ssh root@<vps-ip>. Update the packages:apt update && apt upgrade -y. Install Docker if it is not already present:curl -fsSL https://get.docker.com | sh. Verify Docker Compose is available:docker compose version.Create the project directory
Create a dedicated directory:
mkdir -p /opt/limesurvey && cd /opt/limesurvey. This folder will hold thedocker-compose.ymlfile, the.envenvironment file and, later, the Nginx configuration.Write the docker-compose.yml file
Define three services in your
docker-compose.yml: MariaDB (imagemariadb:10.11, named volumedb_datafor persistence), LimeSurvey (official imagemartialblog/limesurvey:latest, internal port8080, environment variablesDB_HOST,DB_USERNAME,DB_PASSWORD,DB_NAME, andADMIN_USER/ADMIN_PASSWORDfor first-run setup), and an Nginx service (imagenginx:alpine, ports80:80and443:443, volumes on/etc/nginx/conf.dand/etc/letsencrypt). Declare an internal networklimesurvey-netshared by all three services.Configure the environment variables
Create a
.envfile in/opt/limesurveyand fill in the sensitive values:DB_ROOT_PASSWORD,DB_USERNAME,DB_PASSWORD,DB_NAME=limesurvey,ADMIN_USER,ADMIN_PASSWORDandADMIN_EMAIL. The LimeSurvey image reads these variables on first startup to initialise the database. Never commit this file to a Git repository.Obtain a TLS certificate with Certbot
Before starting Nginx in HTTPS mode, get a Let's Encrypt certificate:
apt install certbot -ythencertbot certonly --standalone -d surveys.your-domain.com. The certificate is placed in/etc/letsencrypt/live/surveys.your-domain.com/. Mount this path as a volume in the Nginx container.Write the Nginx configuration
In
/opt/limesurvey/nginx/conf.d/limesurvey.conf, create a virtual host that redirects port 80 to 443, then forwards HTTPS traffic to the LimeSurvey container athttp://limesurvey:8080. Add the headersX-Frame-Options SAMEORIGIN,X-Content-Type-Options nosniffandStrict-Transport-Securityto harden the configuration from the start. The internal hostnamelimesurveyis resolved by the Docker network.Start the containers
From
/opt/limesurvey, launch everything:docker compose up -d. Check that all three services are running:docker compose ps. If LimeSurvey takes a few seconds to start while MariaDB finishes initialising its schema, wait untildocker compose logs limesurveyshowsApplication is ready.Open the admin interface and create your first survey
Navigate to
https://surveys.your-domain.com/admin. Log in with theADMIN_USERandADMIN_PASSWORDcredentials set in your.env. On first access, LimeSurvey guides you through setting the default language and general parameters. Create a test survey to confirm that responses are being recorded in the database.
LimeSurvey self-hosted vs Typeform vs LimeSurvey Cloud
Scroll the table
| Criterion | LimeSurvey self-hosted | Typeform Basic+ | LimeSurvey Cloud Business |
|---|---|---|---|
| Licence | GPL-2, free | Proprietary SaaS | Proprietary SaaS |
| Annual cost (agency, 5 projects) | VPS cost only (299 DH/month) | Around 900 €/year (after July 2026 increase) | Around ~65 $/month |
| Response quota | No limit (local storage) | Capped by plan | Capped by plan |
| Data control | Total — data stays on your server | At Typeform | At LimeSurvey GmbH |
| Conditional logic | Full in the community edition | Limited on Basic+ | Full |
| Updates | On your schedule | Automatic (imposed) | Automatic (imposed) |
Post-installation hardening
Once LimeSurvey is running, apply these security settings immediately. In the administration interface, disable public registration (Global settings → Security → No public registration) unless you need third parties to create accounts. Change the default MariaDB table prefix (lime_) to something specific to your deployment — this limits the impact of generic SQL injection attempts. On the Docker side, keep the MariaDB container isolated on the internal limesurvey-net network with no port 3306 exposed externally: docker inspect limesurvey-db should show no port bound on 0.0.0.0. Finally, schedule a daily backup of the db_data volume with docker run --rm -v limesurvey_db_data:/data -v /opt/backups:/backup alpine tar czf /backup/limesurvey-db-$(date +%F).tar.gz /data.
Post-installation configuration: essential settings
After the first start, a few settings make LimeSurvey ready for professional use. Start with user management: create one account per client (or per project manager), and assign it only the survey groups that belong to that client. Rights are granular: a user can create and edit their own surveys without accessing another client's statistics.
Then configure email sending (Global settings → Email) for invitations and reminders. LimeSurvey can relay through an external SMTP server — use a transactional relay (Postmark, Mailgun, Amazon SES) rather than the machine's own mail server, to ensure invitation deliverability.
Finally, enable Nginx access log rotation and configure logrotate to prevent log files from filling the disk over the months. A widely distributed survey can generate several gigabytes of logs within a few weeks.
Troubleshooting: common errors on first installation
A few error messages come up regularly on a first LimeSurvey Docker installation.
SQLSTATE[HY000] [2002] Connection refused — LimeSurvey is attempting to reach MariaDB before it has finished initialising. Add a depends_on with condition: service_healthy in your docker-compose.yml, paired with a healthcheck on the MariaDB container (mysqladmin ping -h localhost). Without this guard, LimeSurvey starts too early and displays a blank page.
403 Forbidden on the admin interface — The Nginx virtual host is not forwarding requests to LimeSurvey. Check that the hostname in proxy_pass matches exactly the service name declared in docker-compose.yml. A Windows-style line ending in the Nginx configuration file can also trigger this on Linux.
Error: Could not connect to the database server — The database name or credentials in the .env file do not match those passed to the MariaDB container. Remove the db_data volume, fix the .env, then restart: docker compose down -v && docker compose up -d. Warning: this erases all data — only do this before your first real survey.
413 Request Entity Too Large — A respondent is trying to upload a file larger than Nginx's default threshold (1 MB). Add client_max_body_size 20m; to your server block in Nginx and restart the container: docker compose restart nginx.
Next steps and related reading
Self-hosted LimeSurvey fits well into a broader ecosystem of self-hosted tools. If you already run several clients on a single VPS, the article WordPress multisite for agencies covers data separation and access patterns for a similar multi-client setup. For notifications and mailing lists tied to your survey campaigns, self-hosted Listmonk complements LimeSurvey by handling bulk sending from the same infrastructure. Finally, if your agency manages invoicing and project tracking alongside its research work, self-hosted Odoo 17 Community can run on the same VPS or on a dedicated machine depending on your volume.