Commit 2913de9f78
Unsigned
Layout: unified · split
content/blog/2025-01-23-self-hosting-tandoor.org added +144
| @@ -0,0 +1,144 @@ | |||
| 1 | #+date: <2025-01-23 Thu 20:44:45> | ||
| 2 | #+title: Self-Hosting Tandoor Recipe Manager | ||
| 3 | #+description: Learn how to self-host Tandoor, the smart recipe management web app. | ||
| 4 | #+filetags: :self-hosting: | ||
| 5 | #+slug: self-hosting-tandoor | ||
| 6 | |||
| 7 | * Overview | ||
| 8 | |||
| 9 | [[https://tandoor.dev/][Tandoor]] is a smart recipe manager web application that allows you to: | ||
| 10 | - Store your recipes | ||
| 11 | - Search for recipes and ingredients | ||
| 12 | - Share recipes with a link and permission system | ||
| 13 | - Put recipes and ingredients into a shopping list | ||
| 14 | - Plan your meals with a built-in calendar | ||
| 15 | - Calculate nutritional values | ||
| 16 | - Import recipes from websites and apps | ||
| 17 | - Load existing recipes | ||
| 18 | |||
| 19 | * Installation | ||
| 20 | |||
| 21 | [[https://docs.tandoor.dev/][The Tandoor docs]] contain all of the relevant information needed to get start | ||
| 22 | with the self-hosting process. | ||
| 23 | |||
| 24 | This tutorial will use Docker Compose and Nginx on Ubuntu 24.04.1. | ||
| 25 | |||
| 26 | ** Docker Compose | ||
| 27 | |||
| 28 | On your machine, create a directory for Tandoor and copy down the =.env= and | ||
| 29 | =docker-compose.yml= templates: | ||
| 30 | |||
| 31 | #+begin_src shell | ||
| 32 | mkdir ~/tandoor cd ~/tandoor wget | ||
| 33 | https://raw.githubusercontent.com/vabene1111/recipes/develop/.env.template -O .env wget | ||
| 34 | # Plain version of docker-compose.yml | ||
| 35 | https://raw.githubusercontent.com/vabene1111/recipes/develop/docs/install/docker/plain/docker-compose.yml | ||
| 36 | #+end_src | ||
| 37 | |||
| 38 | Within these files, customize as needed. | ||
| 39 | 1. =.env= | ||
| 40 | a. Add a =SECRET_KEY= | ||
| 41 | b. Define the =ALLOWED_HOSTS= | ||
| 42 | c. Set the =POSTGRES_PASSWORD= | ||
| 43 | 2. =docker-compose.yml= | ||
| 44 | a. Update the =ports= since Nginx on my host is already using port 80 (e.g. | ||
| 45 | =8087:80=) | ||
| 46 | |||
| 47 | Once you've updated and saved the files, you can launch the container. | ||
| 48 | |||
| 49 | #+begin_src shell | ||
| 50 | sudo docker compose up -d | ||
| 51 | #+end_src | ||
| 52 | |||
| 53 | The application is now available at =localhost:8087= or =ip_address:8087= if | ||
| 54 | accessing via a different machine. If accessing via a different machine, | ||
| 55 | remember to allow port 8087 through any existing firewalls. | ||
| 56 | |||
| 57 | ** Nginx Reverse Proxy | ||
| 58 | |||
| 59 | Now that Tandoor is available locally, let's connect it to the Nginx web server | ||
| 60 | running on the host machine. | ||
| 61 | |||
| 62 | > Note: I use Nginx configuration files within the =conf.d= directory, but you | ||
| 63 | > may need to use the =sites-available= directory, depending on your | ||
| 64 | > installation of Nginx. | ||
| 65 | |||
| 66 | #+begin_src shell | ||
| 67 | cd /etc/nginx/conf.d/ | ||
| 68 | sudo nano recipes.conf | ||
| 69 | #+end_src | ||
| 70 | |||
| 71 | Within this file, define your website configuration. The example below is my | ||
| 72 | default configuration and utilizes a wildcard certificate for =*.example.com= | ||
| 73 | that covers all of my subdomains. If you don't have a wildcard certificate, you | ||
| 74 | will need to generate an SSL certificate for your domain. | ||
| 75 | |||
| 76 | #+begin_src config | ||
| 77 | server { | ||
| 78 | listen 443 ssl; | ||
| 79 | listen [::]:443 ssl; | ||
| 80 | http2 on; | ||
| 81 | server_name recipes.example.com; | ||
| 82 | |||
| 83 | # SSL | ||
| 84 | ssl_certificate /etc/letsencrypt/live/example.com/fullchain.pem; | ||
| 85 | ssl_certificate_key /etc/letsencrypt/live/example.com/privkey.pem; | ||
| 86 | ssl_trusted_certificate /etc/letsencrypt/live/example.com/chain.pem; | ||
| 87 | |||
| 88 | # reverse proxy | ||
| 89 | location / { | ||
| 90 | proxy_pass http://localhost:8087/; | ||
| 91 | proxy_set_header Host $http_host; | ||
| 92 | proxy_set_header X-Forwarded-Proto $scheme; | ||
| 93 | proxy_redirect http://127.0.0.1:8080 https://recipes.example.com; | ||
| 94 | } | ||
| 95 | |||
| 96 | location /media/ { | ||
| 97 | root /media/; | ||
| 98 | index index.html index.htm; | ||
| 99 | } | ||
| 100 | } | ||
| 101 | |||
| 102 | # HTTP redirect | ||
| 103 | server { | ||
| 104 | listen 80; | ||
| 105 | listen [::]:80; | ||
| 106 | server_name recipes.example.com; | ||
| 107 | include custom.d/letsencrypt.conf; | ||
| 108 | |||
| 109 | if ($host ~ ^[^.]+\.example\.com$) { | ||
| 110 | return 301 https://$host$request_uri; | ||
| 111 | } | ||
| 112 | } | ||
| 113 | #+end_src | ||
| 114 | |||
| 115 | Save and close the configuration file and then restart the web server. | ||
| 116 | |||
| 117 | #+begin_src shell | ||
| 118 | sudo systemctl restart nginx.service | ||
| 119 | #+end_src | ||
| 120 | |||
| 121 | The app is now available on your custom domain! | ||
| 122 | |||
| 123 | ** Screenshots | ||
| 124 | |||
| 125 | #+caption: Login | ||
| 126 | [[https://img.cleberg.net/blog/20250123-self-hosting-tandoor/login.png]] | ||
| 127 | |||
| 128 | #+caption: Recipes | ||
| 129 | [[https://img.cleberg.net/blog/20250123-self-hosting-tandoor/recipes.png]] | ||
| 130 | |||
| 131 | #+caption: Meal Plan | ||
| 132 | [[https://img.cleberg.net/blog/20250123-self-hosting-tandoor/mealplan.png]] | ||
| 133 | |||
| 134 | #+caption: Shopping Lists | ||
| 135 | [[https://img.cleberg.net/blog/20250123-self-hosting-tandoor/shopping.png]] | ||
| 136 | |||
| 137 | #+caption: Cook Book | ||
| 138 | [[https://img.cleberg.net/blog/20250123-self-hosting-tandoor/cookbook.png]] | ||
| 139 | |||
| 140 | #+caption: Import | ||
| 141 | [[https://img.cleberg.net/blog/20250123-self-hosting-tandoor/import.png]] | ||
| 142 | |||
| 143 | #+caption: Administration Panel | ||
| 144 | [[https://img.cleberg.net/blog/20250123-self-hosting-tandoor/admin.png]] | ||
theme/templates/index.html +7 −6
| @@ -8,6 +8,13 @@ uid [ultimate] Christian Cleberg <hello@cleberg.net></pre> | |||
| 8 | <section> | 8 | <section> |
| 9 | <h2>Recent Blog Posts</h2> | 9 | <h2>Recent Blog Posts</h2> |
| 10 | 10 | ||
| 11 | <div class="post"> | ||
| 12 | <time datetime="2025-01-23 20:44:45">2025-01-23</time> | ||
| 13 | <a href="/blog/self-hosting-tandoor.html" | ||
| 14 | >Self-Hosting Tandoor Recipe Manager</a | ||
| 15 | > | ||
| 16 | </div> | ||
| 17 | |||
| 11 | <div class="post"> | 18 | <div class="post"> |
| 12 | <time datetime="2024-12-29 17:45:00">2024-12-29</time> | 19 | <time datetime="2024-12-29 17:45:00">2024-12-29</time> |
| 13 | <a href="/blog/self-hosting-the-lounge.html" | 20 | <a href="/blog/self-hosting-the-lounge.html" |
| @@ -21,12 +28,6 @@ uid [ultimate] Christian Cleberg <hello@cleberg.net></pre> | |||
| 21 | >Using Ollama As a Code Assistant in VS Codium</a | 28 | >Using Ollama As a Code Assistant in VS Codium</a |
| 22 | > | 29 | > |
| 23 | </div> | 30 | </div> |
| 24 | <div class="post"> | ||
| 25 | <time datetime="2024-09-23 19:52:20">2024-09-23</time> | ||
| 26 | <a href="/blog/self-hosting-transmission.html" | ||
| 27 | >Self-Hosting Transmission Bittorrent Client</a | ||
| 28 | > | ||
| 29 | </div> | ||
| 30 | 31 | ||
| 31 | <br /> | 32 | <br /> |
| 32 | <a href="/blog/">All Posts →</a> | 33 | <a href="/blog/">All Posts →</a> |