{"id":16817670,"url":"https://github.com/rap2hpoutre/laravel-prod-server","last_synced_at":"2025-04-11T02:25:22.465Z","repository":{"id":66294513,"uuid":"72866018","full_name":"rap2hpoutre/laravel-prod-server","owner":"rap2hpoutre","description":"Install and run a production server for a Laravel application","archived":false,"fork":false,"pushed_at":"2017-04-10T13:20:37.000Z","size":12,"stargazers_count":23,"open_issues_count":0,"forks_count":7,"subscribers_count":3,"default_branch":"master","last_synced_at":"2025-03-24T23:51:26.539Z","etag":null,"topics":["laravel","server","tutorial"],"latest_commit_sha":null,"homepage":"","language":null,"has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"unlicense","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/rap2hpoutre.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2016-11-04T16:34:55.000Z","updated_at":"2024-12-31T09:47:22.000Z","dependencies_parsed_at":"2023-02-22T13:00:52.895Z","dependency_job_id":null,"html_url":"https://github.com/rap2hpoutre/laravel-prod-server","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/rap2hpoutre%2Flaravel-prod-server","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/rap2hpoutre%2Flaravel-prod-server/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/rap2hpoutre%2Flaravel-prod-server/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/rap2hpoutre%2Flaravel-prod-server/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/rap2hpoutre","download_url":"https://codeload.github.com/rap2hpoutre/laravel-prod-server/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":248328658,"owners_count":21085364,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["laravel","server","tutorial"],"created_at":"2024-10-13T10:47:55.604Z","updated_at":"2025-04-11T02:25:22.456Z","avatar_url":"https://github.com/rap2hpoutre.png","language":null,"funding_links":[],"categories":[],"sub_categories":[],"readme":"# Install and run a production server for a Laravel application\n\nYou already own:\n- A domain name\n- A Github account\n- A fresh Ubuntu 16.04 Server with root access\n\nYou want to deploy an application for:\n- Laravel with a PostgreSQL database\n- Running on PHP7 and served by Nginx\n- Optionally, Redis for Queue, Session and Cache\n\nIf so, let’s go, this is for you.\n\n## Recipe\n\nLet's say:\n\n- **raphael** is your name.\n- **nantes** is your hostname.\n- **myapp** is your app name.\n\nYou will have to replace each occurrence of theses values in the code below.\n\nThis recipe has 11 steps, it may take half an hour to make it.\n\n1. [Initialization](#initialization)\n2. [Composer](#composer)\n3. [PostgreSQL](#postgresql)\n4. [Firewall](#firewall)\n5. [Application user](application-user)\n6. [Facteur](#facteur)\n7. [Laravel](#laravel)\n8. [Nginx](#nginx)\n9. [Your user](#your-user)\n10. [Disable password auth](#disable-password-auth)\n11. [Https](#https)\n\n### Initialization\n\nConnect to your server with root user. Then, name your host\n```bash\nhostname nantes\n```\n\nInstall packages (PHP7, Nginx, PostgreSQL, etc.)\n```bash\napt update\napt upgrade\napt install php php-mbstring php-xml php-zip git nginx redis-server postgresql fail2ban htop php-pgsql\n```\nYou can go to your server IP with your browser, you should see a welcome message from Nginx\n\n### Composer\n```bash\nphp -r \"copy('https://getcomposer.org/installer', 'composer-setup.php');\"\nphp composer-setup.php\nphp -r \"unlink('composer-setup.php');\"\nmv composer.phar /usr/local/bin/composer\n```\n\n### PostgreSQL\n\nRun `psql`:\n```bash\nsudo -u postgres psql\n```\nCreate the user (don't forget to use your own password):\n```sql\nCREATE ROLE myapp LOGIN UNENCRYPTED PASSWORD 'xxxxx' SUPERUSER INHERIT NOCREATEDB NOCREATEROLE NOREPLICATION;\n```\nWrite down the password, you will need it later. Disconnect from `psql` with `\\q`. Then restart service and create the database:\n```bash\nservice postgresql restart\nsudo -u postgres /usr/bin/createdb --echo --owner=myapp myapp\n```\n### Firewall\nConfigure and enable ufw\n```bash\nufw allow 443\nufw allow 80\nufw allow 22\nufw enable\n```\n### Application user\nYou need to create an application user. It's not your name. Replace **myapp** everywhere with the name of your application.\n```bash\nuseradd myapp\nmkdir -p /home/myapp\nchsh -s /bin/bash myapp\nchown -R myapp:myapp /home/myapp\nsudo -u myapp ssh-keygen -t rsa -b 4096 -C \"myapp\"\n```\nOptional step: Copy your public key, located in `/home/myapp/.ssh/id_rsa.pub`, to your github account or repository (only if the repository is private). It will be required to make continuous delivery work without connecting to your server.\n\n### Facteur\nFacteur is a small tool for initializing and deploying Laravel applications. Install it.\n```bash\ncd /home/myapp\nwget https://github.com/rap2hpoutre/facteur/releases/download/v0.1.0/facteur\nchmod +x facteur\nmv facteur /usr/local/bin/facteur\n```\nInit your app with deployer (replace `https://github.com/your/app.git` with the URL to your git repo).\n```bash\nsudo -u myapp HOME=/home/myapp facteur init www https://github.com/your/app.git\n```\n### Laravel\nCopy `.env.example` to `.env`\n```bash\nsudo -u myapp cp /home/myapp/www/current/.env.example  /home/myapp/www/current/.env\n```\nEdit `/home/myapp/www/current/.env`\n```bash\nvi /home/myapp/www/current/.env\n```\nChange the values of `DB_*` with your credentials.\n```\nDB_CONNECTION=pgsql\nDB_HOST=127.0.0.1\nDB_PORT=5432\nDB_DATABASE=myapp\nDB_USERNAME=myapp\nDB_PASSWORD=xxxxx\n```\nChange `APP_ENV=local` to `APP_ENV=production` (you could disable debug too).\n\nUse redis for everything if you want (but don't forget to include `predis/predis` to your laravel project in that case)\n```\nCACHE_DRIVER=redis\nSESSION_DRIVER=redis\nQUEUE_DRIVER=redis\n```\nGenerate the laravel key:\n```bash\ncd /home/myapp/www/current\nsudo -u myapp php artisan key:generate\n```\nRun your first migration\n```bash\nsudo -u myapp php artisan migrate --force\n```\nAuthorize `www-data` to write in storage:\n```bash\nchown -R www-data:www-data /home/myapp/www/shared/storage\n```\n\n### Nginx\nEdit `/etc/nginx/fastcgi.conf` and replace `SCRIPT_FILENAME` and `DOCUMENT_ROOT` with:\n```nginx\nfastcgi_param SCRIPT_FILENAME $realpath_root$fastcgi_script_name;\nfastcgi_param DOCUMENT_ROOT $realpath_root;\n```\nThen create and edit `/etc/nginx/sites-available/myapp`\n```nginx\nserver {\n    listen 80 default_server;\n    server_name _;\n    root /home/myapp/www/current/public;\n    server_tokens off;\n    ssl_protocols TLSv1 TLSv1.1 TLSv1.2;\n    index index.html index.htm index.php;\n    charset utf-8;\n    location / {\n        try_files $uri $uri/ /index.php?$query_string;\n    }\n    location = /favicon.ico { access_log off; log_not_found off; }\n    location = /robots.txt  { access_log off; log_not_found off; }\n    error_log  /var/log/nginx/hello-error.log error;\n    error_page 404 /index.php;\n    location ~ \\.php$ {\n        fastcgi_split_path_info ^(.+\\.php)(/.+)$;\n        fastcgi_pass unix:/var/run/php/php7.0-fpm.sock;\n        fastcgi_index index.php;\n        include fastcgi.conf;\n    }\n    location ~ /\\.ht {\n        deny all;\n    }\n}\n```\nDisable default Nginx site and enable your myapp site:\n```bash\nrm /etc/nginx/sites-enabled/default\nln -s /etc/nginx/sites-available/myapp /etc/nginx/sites-enabled/myapp\n```\nReload nginx\n```bash\nservice nginx reload\n```\n\nYou should be able to connect to your website with the IP adress.\n\n### Your user\n\nCreate and configure your user (type a password when prompted)\n```bash\nuseradd raphael\nadduser raphael sudo\nchsh -s /bin/bash raphael\nmkdir /home/raphael\nchown -R raphael:raphael /home/raphael\ncp /root/.profile /home/raphael/.profile\ncp /root/.bashrc /home/raphael/.bashrc\npasswd raphael\n```\nGo to your computer (not your server) to authorize your SSH key (replace `ADDRESS` with your address and `raphael` with your name)\n```bash\nssh-copy-id raphael@ADDRESS\n```\nTest if connection works (you should not be prompted for password)\n```bash\nssh raphael@ADDRESS\n```\nNow you should be connected with your account. Good bye `root`, we will not use it anymore.\n\n### Disable password auth\nEdit `/etc/ssh/sshd_config` and add this\n```\nPasswordAuthentication no\n```\nThen run\n```\nsudo service ssh restart\n```\n\n### Https\nEverything is https now, here is how to have one for your domain (replace `your.domain.com`)\n```\nsudo apt install letsencrypt\nsudo service nginx stop\nsudo letsencrypt certonly --standalone -d your.domain.com\n```\n\nEdit `/etc/nginx/sites-available/myapp` and change the first lines\n```nginx\nserver {\n    listen 443 ssl;\n    ssl_certificate /etc/letsencrypt/live/your.domain.com/fullchain.pem;\n    ssl_certificate_key /etc/letsencrypt/live/your.domain.com/privkey.pem;\n    server_name _;\n    # ...\n}\n```\n\nEnable automatic renew of the certificate\n\n```bash\nsudo letsencrypt renew --dry-run --agree-tos\nsudo service nginx start\n```\nEdit `/home/raphael/renew.sh`\n```bash\n#!/bin/bash\nservice nginx stop\nletsencrypt renew\nservice nginx start\n```\n\nEdit `/etc/crontab` and add this\n```\n0 4 * * 0,3 root /home/raphael/renew.sh\n```\n\nRestart nginx\n```bash\nsudo service nginx start\n```\n\n**Your website is ready. Go to https://your.domain.com and it works.**\n\n## Next steps?\n - [Delivery](delivery.md)\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Frap2hpoutre%2Flaravel-prod-server","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Frap2hpoutre%2Flaravel-prod-server","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Frap2hpoutre%2Flaravel-prod-server/lists"}