What’s actually slowing this PC down?
Pick the symptom - the matching free tool is one click away.
iTechGuides is reader-supported. When you buy through links on our site, we may earn an affiliate commission. As an Amazon Associate I earn from qualifying purchases. Learn more
Antihost offers Linux VPS plans with full root access, unlimited traffic on a 1 Gbps port and a 14-day free trial.
A reliable Symfony production deployment is a repeatable release, not a single file copy. Build a tested release, install production-only dependencies, provide secrets through the server environment, compile assets, run Doctrine migrations deliberately, warm the production cache, expose only public/ through Nginx, and keep Messenger workers under a process manager. This guide shows that workflow on an Ubuntu VPS while marking the choices that must match your application’s composer.json, Symfony branch, PHP extensions, database, and Ubuntu release.
What a Symfony production release must accomplish
Symfony’s deployment documentation describes deployment as a complex task whose details vary with the application and hosting setup. The stable part is the release sequence: deploy versioned code, install vendor dependencies, provide production configuration, migrate the database, handle assets, and clear or warm the cache. The VPS also needs a hardened operating system, HTTPS, backups, logging, monitoring, and a rollback procedure.
- Application: the exact Symfony branch, PHP version, required extensions, database engine and version, Messenger transports, and asset tool are known.
- Release: code and dependencies are built in an identifiable release directory rather than edited in place.
- Configuration: production secrets are outside Git and commands run with
APP_ENV=prodand debugging disabled. - Web edge: Nginx serves only the
public/directory and forwards PHP execution to PHP-FPM. - State: migrations, uploads, cache, queues, and backups are handled explicitly.
- Operations: workers, logs, health checks, certificate renewal, and rollback are documented.
1. Confirm the compatibility matrix before touching the server
Do not copy a PHP or Ubuntu version from another tutorial and assume it is universal. Read the application’s composer.json, Symfony requirements, deployment files, and lock file first. Record the values you will use for this release.
| Component | What to verify | Why it matters |
|---|---|---|
| Symfony | Major/minor branch and environment requirements | Console commands, cache behavior, Messenger options, and supported PHP versions differ by branch. |
| PHP | Required version and extensions such as PDO, XML, Intl, Ctype, JSON, Mbstring, and OPcache | Composer resolves dependencies against the PHP runtime and extensions actually installed on the VPS. |
| Database | Engine, server version, character set, timezone, connection limits, and TLS or private-network requirements | Doctrine migrations and SQL generated by the application must match the server. |
| Web server | Nginx with PHP-FPM, including the installed FPM socket path | The socket name changes with the PHP package and Ubuntu release. |
| Assets and workers | AssetMapper, Encore, another build tool, and any asynchronous Messenger transports | These add build commands and long-running processes to the release. |
Keep this matrix in the repository or deployment documentation. If the application requires a PHP extension that the Ubuntu package does not provide, resolve that before scheduling the cutover.
#1 Best Overall
- Read Before You Buy — No Video Output: These adapters support charging and USB 2.0 data transfer, but cannot transmit video signals. Except for standard USB webcams (which use USB data only), they are not compatible with HDMI/DisplayPort cables, video-capable USB-C hubs, or docking stations with video output.
- Convert USB-A Ports to USB-C: Designed to connect USB-C earphones, cables, flash drives, card readers, and other USB-C accessories to standard USB-A ports. Plug-and-play with no drivers or software required.
- Aluminum Alloy Housing: Built with a sturdy aluminum alloy shell that aids in heat dissipation and protects against daily wear and scratches. Designed to maintain a stable and secure connection.
- Compact & Travel-Friendly: The ultra-compact design allows the adapter to stay plugged into your device without blocking adjacent ports or adding bulk, reducing wear and tear on your original USB ports.
- 12-Month Warranty: Backed by a 12-month manufacturer warranty for peace of mind. Designed to meet strict quality control standards for reliable everyday performance.
2. Prepare and harden the Ubuntu VPS
Create a deployment account and secure SSH
Use a non-root account such as deploy for releases. Install its public SSH key, confirm that key-based login works in a second terminal, and only then disable password authentication and direct root login in the SSH server configuration. Keep one tested administrative access path before closing the original session.
sudo adduser deploy
sudo usermod -aG sudo deploy
sudo install -d -m 700 /home/deploy/.ssh
sudo install -m 600 /tmp/deploy-authorized_keys /home/deploy/.ssh/authorized_keys
sudo chown -R deploy:deploy /home/deploy/.ssh
The final SSH settings depend on your Ubuntu release and access policy, but the target state is an SSH key for administration, no password login, and no routine application work as root.
Apply updates, time synchronization, and a firewall
sudo apt update
sudo apt full-upgrade
sudo timedatectl set-ntp true
sudo apt install ufw
sudo ufw allow OpenSSH
sudo ufw allow 80/tcp
sudo ufw allow 443/tcp
sudo ufw enable
sudo ufw status verbose
Allow only ports required by the application. Do not expose a database port to the public internet when the database is local or reachable through a private network. Cloud firewall rules, provider security groups, and the VPS firewall must agree.
Choose a filesystem layout
A release layout makes an atomic rollback possible and keeps mutable data away from code. One practical arrangement is:
/var/www/symfony-app/
├── current -> releases/release-20261015-1200
├── releases/
│ ├── release-20261015-1200/
│ └── release-20261014-1830/
└── shared/
├── .env.local
├── uploads/
└── var/
Keep only the number of old releases that your disk and rollback policy allow. Link the shared environment file and upload directory into each release. Because Nginx’s document root will be current/public, shared uploads should be exposed through an intentional Symfony route or a controlled public directory, never by placing secrets in public/.
3. Install Nginx, PHP-FPM, Composer, and database tools
Install the package names that match the Ubuntu release and the PHP version selected in your compatibility matrix. The following is an example shape, not a universal version prescription:
The Tool Desk
Outbyte Driver Updater FREEFix the driver behind crashes, sound loss and screen glitchesFind Drivers →Outbyte PC Repair FREERepair Windows errors before they cause bigger problemsFix Now →sudo apt update
sudo apt install nginx php-fpm php-cli php-xml php-mbstring php-intl php-mysql php-curl php-zip unzip git
sudo systemctl enable --now nginx
sudo systemctl enable --now php8.3-fpm
Replace php8.3-fpm and extension packages with the versions your repository supplies. Install Composer using its current verified installation method, then confirm both commands as the deployment user:
Rank #2
- 5-in-1 USB-C Hub: Experience comprehensive connectivity featuring a Power Delivery input, two USB-A 2.0 ports, a USB-A 3.0 port, and an HDMI port. (Note: The USB-C power delivery input port is only for connecting an external wall charger to power your laptop and cannot power peripheral devices.)
- 90W Pass-Through Charging: Achieve optimal charging with 90W pass-through power to your laptop, supported by a total input of 100W, with the hub reserving 10W for operational efficiency. (Note: Wall charger not included.)
- Quick Data Transfers: Accelerate your productivity with rapid data transfers using a high-speed 5Gbps USB 3.0 port and two 480Mbps USB 2.0 ports.
- 4K HDMI Display: Enhance your visual experience with a hub capable of delivering 4K resolution at 30Hz in both mirror and extend modes. Please note that this hub is compatible with MacBook (macOS 12 and newer), Windows 10 and 11, ChromeOS, and laptops equipped with DP Alt Mode and Power Delivery. Note: This device is not compatible with Linux.
- What You Get: Anker USB-C Hub (5-in-1, 4K HDMI), welcome guide, 18-month warranty, and our friendly customer service.
php -v
php -m
composer --version
Check the actual FPM socket rather than guessing it:
ls -l /run/php/
A typical socket is /run/php/php8.3-fpm.sock, but the filename is release-specific. Nginx must use exactly the socket installed on this server.
Database placement and credentials
Create a least-privilege application database user. If the database is on the VPS, bind it to localhost or a private interface and restrict its local firewall access. If it is separate, use the provider’s private network or TLS guidance. Store the complete Doctrine connection string in the server environment, not in Git, and verify that its character set and timezone agree with the application.
4. Store production configuration outside the repository
Production configuration belongs to the deployment environment. Never commit database passwords, API tokens, private keys, or the production APP_SECRET. A common arrangement is a root-owned or deployment-owned shared file at /var/www/symfony-app/shared/.env.local, linked into the active release with permissions that let PHP read it but do not make it world-readable.
APP_ENV=prod
APP_DEBUG=0
APP_SECRET=use-a-long-random-value
DATABASE_URL=mysql://app_user:password@127.0.0.1:3306/app_db
MESSENGER_TRANSPORT_DSN=...
Use your application’s actual variable names and transport DSN. Symfony’s console commands must see the same environment as PHP-FPM. Before a release, test a harmless command explicitly:
APP_ENV=prod APP_DEBUG=0 php bin/console about
If you use encrypted secrets, a process manager environment file, or the hosting platform’s secret store instead of .env.local, apply the same rule: secrets are injected on the server and are available to both web requests and workers.
5. Build and publish a versioned release
Run the following sequence from a fresh release directory. Fetch a tagged commit or immutable artifact so you can identify exactly what is running.
PC Slower Than It Used to Be?
A free scan shows the junk files, broken settings and background clutter dragging Windows down - then fixes them in one click.Free scan · Windows 10 & 11Outdated Drivers Are Slowing You Down
One free scan finds every outdated or missing driver and matches the right update for your exact hardware.Free scan · exact hardware matchRank #3
- Sleek 7-in-1 USB-C Hub: Features an HDMI port, two USB-A 3.0 ports, and a USB-C data port, each providing 5Gbps transfer speeds. It also includes a USB-C PD input port for charging up to 100W and dual SD and TF card slots, all in a compact design.
- Flawless 4K@60Hz Video with HDMI: Delivers exceptional clarity and smoothness with its 4K@60Hz HDMI port, making it ideal for high-definition presentations and entertainment. (Note: Only the HDMI port supports video projection; the USB-C port is for data transfer only.)
- Double Up on Efficiency: The two USB-A 3.0 ports and a USB-C port support a fast 5Gbps data rate, significantly boosting your transfer speeds and improving productivity.
- Fast and Reliable 85W Charging: Offers high-capacity, speedy charging for laptops up to 85W, so you spend less time tethered to an outlet and more time being productive.
- What You Get: Anker USB-C Hub (7-in-1), welcome guide, 18-month warranty, and our friendly customer service.
- Create the directory and obtain code. Make
/var/www/symfony-app/releases/<release-id>, then clone the approved commit or unpack the CI artifact there. Do not edit the active directory. - Link shared state. Link
shared/.env.local, uploads, and any other documented persistent files into the release. Keepvar/cacheandvar/logwritable by the account that runs Symfony commands and by PHP-FPM as required. - Install production dependencies. Run:
composer install --no-dev --prefer-dist --optimize-autoloader --no-interaction
Use the committed composer.lock. If Composer scripts execute Symfony commands, ensure the production environment file is already linked before running the install.
- Build frontend assets. For Encore or another Node-based build, use the project’s pinned Node version and run commands such as
npm cifollowed bynpm run build. For AssetMapper applications, run the asset compilation command required by that Symfony version, commonlyphp bin/console asset-map:compile --env=prod. Do not run both workflows unless the application uses both. - Check the release before cutover. Run the application’s tests, a production container compile if applicable, and a read-only console check. Stop here if dependency installation, asset compilation, or configuration validation fails.
6. Run Doctrine migrations as a deliberate release operation
Back up the database before a migration that changes schema or data. Deploy code that can work with the current schema first when possible, then run the migration and observe its output:
APP_ENV=prod APP_DEBUG=0 php bin/console doctrine:migrations:status
APP_ENV=prod APP_DEBUG=0 php bin/console doctrine:migrations:migrate --no-interaction
Review the generated migration, lock behavior, expected duration, and application compatibility before running it on production. A migration that removes a column or changes data formats may not be safely reversible. For destructive changes, use an expand-and-contract plan: add the new structure, deploy code that writes both forms if necessary, backfill, switch reads, and remove the old structure only in a later release.
If the migration fails, do not switch the active symlink automatically. Preserve the error and database state, correct the release or migration in a controlled change, and use the backup or a tested forward fix according to your recovery plan.
Free tools Windows power users keep installed
One-click scans. No signup required.
7. Clear and warm the Symfony production cache
Cache commands must run against the release that will become active and with production settings:
APP_ENV=prod APP_DEBUG=0 php bin/console cache:clear
APP_ENV=prod APP_DEBUG=0 php bin/console cache:warmup
Some Symfony versions warm the cache as part of cache:clear; running cache:warmup explicitly makes the intended step visible. Ensure the cache and log directories are writable, and watch the command for missing environment variables, unavailable services, or invalid container definitions.
8. Configure Nginx to expose only public/
Point the virtual host root at the active release’s public directory. The exact configuration can vary, but this pattern serves existing assets, internally routes other requests to Symfony’s front controller, passes only that front controller to PHP-FPM, and rejects other PHP files:
Quick wins for a faster PC:
Scan for outdated or missing drivers - takes under a minuteDriver Scan →Clear out junk files and repair common Windows errorsFree Scan →Fix the driver behind crashes, sound loss and screen glitchesFind Drivers →Rank #4
- Dual Converters, Infinite Potential:Includes 2× USB C male to USB A female adapters and 2× USB A male to USB C female adapters. Perfect for a wide range of uses—tablets with Bluetooth keyboards, expand USB ports on macbook, and more. Two different converters for all your daily needs
- Next-Level 10Gbps & 3A Charging: No more slow 480Mbps, this usb to usb c adapter has a transfer speed of up to 10Gbps, allowing you to do more transferring in less time. This usb adapter fits both USB A and USB C charger, supporting up to 3A fast charging
- Upgraded Exquisite Craftsmanship: With an aluminum alloy housing and metal connector, the usbc to usb adapter is extremely durable and sturdy. Rigorously tested to withstand more than 10,000 times of plugging and unplugging, ensuring long-lasting performance
- Broad Compatible: The usb c to usb adapter widely supports all USB C/ USB A devices like laptops, tablets, cellphones, car chargers, and phone chargers. Such as compatible with MacBook Pro/Air 2023/2022, Thunderbolt 4/3 Devices,Apple MagSafe Watch 9/8/7/SE/Ultra, iPad Pro 2022/2021, Samsung Galaxy S23/S20/S10, and iPhone 17/16/15 Pro. Plug and play
- Please Note: To reach 10Gbps speed, keep the cable under 3.3 ft. For USB A Male to USB C adapters, try flipping the USB C connector. USB C Male to USB A adapters support bidirectional 10Gbps transfer within 3.3 ft
server {
listen 80;
server_name app.example.com;
root /var/www/symfony-app/current/public;
index index.php;
location / {
try_files $uri $uri/ /index.php$is_args$args;
}
location = /index.php {
internal;
include fastcgi_params;
fastcgi_param SCRIPT_FILENAME $realpath_root$fastcgi_script_name;
fastcgi_param DOCUMENT_ROOT $realpath_root;
fastcgi_pass unix:/run/php/php8.3-fpm.sock;
}
location ~ .php$ {
return 404;
}
location ~ /. {
deny all;
}
}
Replace the domain, root, and socket with your values. The internal directive means a browser cannot request /index.php directly; Nginx can still reach it through the internal fallback. The final PHP rule prevents accidental exposure of scripts such as a forgotten diagnostic file. Because the document root is public/, project files such as src/, config/, vendor/, and .env are outside the web root.
Validate and reload without dropping existing connections:
sudo nginx -t
sudo systemctl reload nginx
sudo systemctl reload php8.3-fpm
If PHP-FPM uses a different service name, reload that service instead. Review Nginx and PHP-FPM logs immediately after the change.
9. Switch the active release atomically
After dependencies, assets, migrations, cache, and configuration checks succeed, point current at the new release in one operation:
ln -sfn /var/www/symfony-app/releases/release-20261015-1200 /var/www/symfony-app/current
Use a release identifier generated by your deployment system rather than copying this example. Reload services only when their configuration changed; an atomic symlink switch is normally enough for Nginx to serve the new code. Confirm that the PHP-FPM user can read the target and write the required shared directories.
| Approach | Release safety | Downtime and recovery | Operational cost |
|---|---|---|---|
| In-place edits | Low: a partial upload can leave mixed code and dependencies | Often requires a maintenance window; recovery is manual | Simple to start, difficult to audit |
| Versioned directories with an active symlink | High: build and validate before cutover | Fast switch and clear previous target; database rollback still needs planning | Requires cleanup and a scripted release process |
| CI/CD artifact with health-checked cutover | Highest when tests, approvals, and immutable artifacts are enforced | Can stop before cutover or revert the symlink after failed checks | More setup, repeatable deployments and audit history |
10. Enable HTTPS and verify the application
Point DNS at the VPS, then obtain a certificate with a maintained ACME client. One common Ubuntu implementation is Certbot with the Nginx plugin:
sudo apt install certbot python3-certbot-nginx
sudo certbot --nginx -d app.example.com
sudo certbot renew --dry-run
Use the ACME client approved by your organization if it differs. Confirm that the client has a renewal timer or equivalent scheduled task, that HTTP redirects to HTTPS, and that the certificate covers every required hostname.
Best Value
- 5-in-1 Connectivity: Equipped with a 4K HDMI port, a 5 Gbps USB-C data port, two 5 Gbps USB-A ports, and a USB C 100W PD-IN port. Note: The USB C 100W PD-IN port supports only charging and does not support data transfer devices such as headphones or speakers.
- Powerful Pass-Through Charging: Supports up to 85W pass-through charging so you can power up your laptop while you use the hub. Note: Pass-through charging requires a charger (not included). Note: To achieve full power for iPad, we recommend using a 45W wall charger.
- Transfer Files in Seconds: Move files to and from your laptop at speeds of up to 5 Gbps via the USB-C and USB-A data ports. Note: The USB C 5Gbps Data port does not support video output.
- HD Display: Connect to the HDMI port to stream or mirror content to an external monitor in resolutions of up to 4K@30Hz. Note: The USB-C ports do not support video output.
- What You Get: Anker 332 USB-C Hub (5-in-1), welcome guide, our worry-free 18-month warranty, and friendly customer service.
Post-cutover checks
- Request the home page and a representative authenticated route over HTTPS.
- Verify a database-backed page and confirm that writes use the expected database.
- Exercise cache reads and writes, including any sessions or application cache pools.
- Test outbound mail, webhooks, and API integrations with safe test data.
- Call the application’s health endpoint if one exists; otherwise perform a documented smoke test.
- Inspect Nginx, PHP-FPM, and Symfony logs for errors, deprecations, permission failures, and slow requests.
- Check disk space, memory, CPU, queue depth, and certificate expiry in monitoring.
11. Keep Symfony Messenger workers alive
If the application uses an asynchronous Messenger transport, a worker started in an SSH session is not a production service. Run consumers under Supervisor or systemd and give them recycling limits. Symfony recommends limits such as --time-limit and --memory-limit so a worker does not run forever as code, libraries, or message payloads accumulate.
Do these 3 things before closing this tab:
1Fix the driver behind crashes, sound loss and screen glitches2Repair Windows errors before they cause bigger problems3Scan for outdated or missing drivers - takes under a minuteSystemd example
[Unit]
Description=Symfony Messenger consumer
After=network.target
[Service]
Type=simple
User=www-data
WorkingDirectory=/var/www/symfony-app/current
Environment=APP_ENV=prod
Environment=APP_DEBUG=0
ExecStart=/usr/bin/php bin/console messenger:consume async --no-interaction --time-limit=3600 --memory-limit=256M
Restart=always
RestartSec=5
KillSignal=SIGTERM
TimeoutStopSec=60
[Install]
WantedBy=multi-user.target
Save this as a service appropriate to your naming convention, then enable it:
sudo systemctl daemon-reload
sudo systemctl enable --now symfony-messenger.service
sudo systemctl status symfony-messenger.service
journalctl -u symfony-messenger.service -f
Use the same environment and shared files as PHP-FPM. Set the number of service instances and transport name to the application’s workload. During a release, ask workers to finish their current message and stop, switch the symlink, then start them again:
sudo -u www-data php /var/www/symfony-app/current/bin/console messenger:stop-workers --env=prod
sudo systemctl restart symfony-messenger.service
The stop command marks workers for graceful termination; coordinate it with your queue visibility timeout so a message is not redelivered unexpectedly.
Supervisor alternative
Supervisor is also suitable when your team already operates it. Configure the command with the same --time-limit, --memory-limit, user, working directory, environment, automatic restart, and log paths. Whether you choose Supervisor or systemd, monitor failed messages and queue depth, and document how many consumers should run after each deployment.
12. Backups, monitoring, and rollback
Back up all state that is not in Git
- Take scheduled, restorable database backups and record retention and encryption settings.
- Back up user uploads and any locally stored generated files.
- Keep backups off the VPS or on a separate failure domain.
- Perform restore drills; a backup that has never been restored is an assumption, not a recovery plan.
Define the rollback boundary
Code rollback is usually a symlink change:
ln -sfn /var/www/symfony-app/releases/release-20261014-1830 /var/www/symfony-app/current
sudo systemctl restart symfony-messenger.service
Do not treat a database migration as automatically reversible. If the new code has already applied an incompatible or destructive schema change, switching back to old PHP files may make the application fail. Your runbook should state the migration state, backup to restore, worker stop procedure, health checks, and who approves a rollback. Test that runbook in staging before the first incident.
Common failure modes and fixes
| Symptom | Likely cause | Action |
|---|---|---|
| 502 Bad Gateway | Nginx points to a missing or inaccessible PHP-FPM socket, or FPM is stopped | Check systemctl status php*-fpm, list /run/php/, correct fastcgi_pass, and inspect the Nginx error log. |
| 403 or 404 for every Symfony route | Wrong document root, missing fallback, or unreadable release | Confirm the root ends in /public, validate try_files, and test permissions as the FPM user. |
| 500 after cutover | Missing secret, incompatible PHP extension, stale cache, or failed service wiring | Run bin/console about with production variables, clear and warm cache, and read var/log/prod.log and PHP-FPM logs. |
| Composer dependency failure | PHP version or extension does not satisfy composer.lock |
Compare the compatibility matrix with php -v and php -m; do not bypass platform checks blindly. |
| Migration cannot connect | Incorrect DATABASE_URL, private-network routing, credentials, or database permissions |
Run the production console command as the deployment account and verify connectivity without printing secrets. |
| Assets return 404 | Build step was skipped, output path differs, or the release link points to the wrong directory | Run the application’s asset build, inspect the generated files under public/, and verify the active symlink. |
| Worker repeatedly exits | Bad DSN, failed message, insufficient memory, or a command running from an old release | Read service logs, inspect failed messages, verify WorkingDirectory, and keep the recycling limits while fixing the underlying error. |
| Uploads disappear after deployment | Uploads were stored inside a release directory | Move them to shared/uploads, link that path into each release, and verify the application’s upload configuration. |
Repeatable release checklist
- Confirm Symfony, PHP, extension, database, asset, and worker compatibility.
- Verify SSH access, updates, firewall rules, time synchronization, disk space, and backups.
- Create an immutable release directory and fetch the approved commit or artifact.
- Link production configuration and persistent storage from
shared/. - Run
composer install --no-dev --prefer-dist --optimize-autoloader --no-interaction. - Build assets using the project’s pinned toolchain.
- Run tests and production configuration checks.
- Back up the database, inspect migration status, and run Doctrine migrations deliberately.
- Clear and warm the production cache.
- Validate Nginx, PHP-FPM, and permissions before cutover.
- Switch the active symlink, reload changed services, and run HTTPS smoke tests.
- Gracefully recycle Messenger workers and inspect queue, log, and error signals.
- Record the active release, migration state, checks performed, and rollback target.
The Bottom Line
Deploy Symfony to an Ubuntu VPS as a versioned, observable release: match the application’s compatibility matrix, keep secrets and state separate from code, run migrations and cache commands in production mode, serve only public/ through Nginx, supervise workers, and test rollback before you need it.
Quick Recap
Product prices and availability are accurate as of the date/time indicated and are subject to change. Any price and availability information displayed on Amazon at the time of purchase will apply.

