<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: kodumbeats</title>
    <description>The latest articles on DEV Community by kodumbeats (@kodumbeats).</description>
    <link>https://dev.to/kodumbeats</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F391679%2F7b6ec8dd-dae7-4b56-bc9d-d2aaa4be7935.jpeg</url>
      <title>DEV Community: kodumbeats</title>
      <link>https://dev.to/kodumbeats</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/kodumbeats"/>
    <language>en</language>
    <item>
      <title>Appwrite Loves Open Source: Why I Chose To Support Lazygit &amp; Lazydocker</title>
      <dc:creator>kodumbeats</dc:creator>
      <pubDate>Wed, 23 Jun 2021 17:29:52 +0000</pubDate>
      <link>https://dev.to/appwrite/appwrite-loves-open-source-why-i-chose-to-support-lazygit-lazydocker-ao</link>
      <guid>https://dev.to/appwrite/appwrite-loves-open-source-why-i-chose-to-support-lazygit-lazydocker-ao</guid>
      <description>&lt;p&gt;Open-source is at the ❤️ of everything we do at Appwrite, and we want to enable and foster the open-source community that helped us grow to nearly 10,000 stars on &lt;a href="https://github.com/appwrite/appwrite"&gt;GitHub&lt;/a&gt;. Open-source projects, though, require a great deal of effort to maintain and grow. We use open-source tools every day to build Appwrite, and we want to help our community. To give back, each Appwrite engineer gets to pick an open-source project for Appwrite to sponsor for one year. &lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;We're building Appwrite, an open-source Backend-as-a-Service (BaaS), packaged as a set of Docker microservices, to give developers of any background the tools necessary to build modern apps quickly and securely. Come chat with us on Discord.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Git and Docker Are Hard
&lt;/h2&gt;

&lt;p&gt;I like terminal apps for the same reason I prefer Vim in a &lt;code&gt;tmux&lt;/code&gt; session over VSCode: I need a simple, fast interface to complete my job quickly. &lt;a href="https://www.docker.com/"&gt;Docker&lt;/a&gt; 🐋 and &lt;a href="https://git-scm.com/"&gt;Git&lt;/a&gt; are ubiquitous in the development world, but just like Vim, take a lot of effort to learn all of the power they offer. In short, &lt;code&gt;git&lt;/code&gt; and &lt;code&gt;docker&lt;/code&gt; are &lt;em&gt;hard&lt;/em&gt;. 🤕 &lt;a href="https://stackoverflow.com/questions/804115/when-do-you-use-git-rebase-instead-of-git-merge"&gt;What’s a rebase?&lt;/a&gt; &lt;a href="https://stackoverflow.com/questions/30172605/how-do-i-get-into-a-docker-containers-shell"&gt;What’s that command to shell into a container?&lt;/a&gt; &lt;a href="https://stackoverflow.com/questions/161813/how-to-resolve-merge-conflicts-in-git-repository"&gt;How do I resolve a merge conflict?&lt;/a&gt; If StackOverflow is any indication, these tools are &lt;em&gt;confusing&lt;/em&gt; at least. &lt;/p&gt;

&lt;p&gt;Docker and Git are wonderfully powerful CLI tools, but I have to &lt;em&gt;remember which command to use&lt;/em&gt;. 🤔 Even more, I only have access to the information I specifically request, which slows my workflow. To assist in development, I reach for the wonderful &lt;a href="https://github.com/jesseduffield/lazygit"&gt;&lt;code&gt;lazygit&lt;/code&gt;&lt;/a&gt; and &lt;a href="https://github.com/jesseduffield/lazydocker"&gt;&lt;code&gt;lazydocker&lt;/code&gt;&lt;/a&gt;, both developed by Jesse Duffield. They’re both written in Go and each provide a mouse-friendly terminal interface 🖥️ to work with &lt;code&gt;git&lt;/code&gt; repositories and &lt;code&gt;docker&lt;/code&gt; environments. They’re most impressive in action:&lt;/p&gt;

&lt;h3&gt;
  
  
  Lazygit
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fosvuvnsbhzyaleozcclu.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fosvuvnsbhzyaleozcclu.png" alt="Lazygit" width="800" height="507"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Lazydocker
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fk0xerndeaqq2aadqm8qh.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fk0xerndeaqq2aadqm8qh.png" alt="Lazydocker" width="800" height="507"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Both of these products have helped me save loads of time ⌛ and effort while traveling my path as a developer. If you're new to &lt;code&gt;git&lt;/code&gt; or &lt;code&gt;docker&lt;/code&gt;, or are just a bit lazy like I am, check out these products for yourself. &lt;/p&gt;

&lt;h2&gt;
  
  
  Open-source Software (OSS) Is Hard
&lt;/h2&gt;

&lt;p&gt;Since Appwrite is open-source, we understand the challenges that OSS projects face. If you fall in love ❤️ with an open-source project (like we have), consider checking out ways to contribute. Most OSS projects happily accept contributions in their own way, whether they be in the form of commits, bug 🐛 reports, advocacy, or even monetary 💰 support. If you love &lt;code&gt;lazygit&lt;/code&gt; and/or &lt;code&gt;lazydocker&lt;/code&gt;, consider joining us as a &lt;a href="https://github.com/sponsors/jesseduffield"&gt;GitHub Sponsor&lt;/a&gt;. Or, if you're interested in contributing to Appwrite, check out our &lt;a href="https://github.com/appwrite/appwrite/blob/master/CONTRIBUTING.md"&gt;contribution guide&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Learn more about Appwrite
&lt;/h2&gt;

&lt;p&gt;Check out Appwrite as the backend for your next &lt;a href="https://appwrite.io/docs/getting-started-for-web"&gt;web&lt;/a&gt;, &lt;a href="https://appwrite.io/docs/getting-started-for-flutter"&gt;Flutter&lt;/a&gt;, or &lt;a href="https://appwrite.io/docs/getting-started-for-server"&gt;server-side&lt;/a&gt; application. Here are some handy links for more information:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://github.com/appwrite/appwrite/blob/master/CONTRIBUTING.md"&gt;Appwrite Contribution Guide&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://appwrite.io/discord"&gt;Appwrite Discord&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/appwrite"&gt;Appwrite Github&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://appwrite.io/docs"&gt;Appwrite Documentation&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>opensource</category>
      <category>appwrite</category>
      <category>docker</category>
      <category>lazydocker</category>
    </item>
    <item>
      <title>#30DaysOfAppwrite: Docker Swarm Integration</title>
      <dc:creator>kodumbeats</dc:creator>
      <pubDate>Fri, 28 May 2021 12:43:54 +0000</pubDate>
      <link>https://dev.to/appwrite/30daysofappwrite-docker-swarm-integration-2io9</link>
      <guid>https://dev.to/appwrite/30daysofappwrite-docker-swarm-integration-2io9</guid>
      <description>&lt;h2&gt;
  
  
  Intro
&lt;/h2&gt;

&lt;p&gt;&lt;a href="http://30days.appwrite.io/"&gt;#30DaysOfAppwrite&lt;/a&gt; is a month-long event focused on giving developers a walk-through of all of Appwrite's features, starting from the basics to more advanced features like Cloud Functions! Alongside we will also be building a fully-featured Medium clone to demonstrate how these concepts can be applied when building a real-world app. We also have some exciting prizes for developers who follow along with us!&lt;/p&gt;

&lt;h2&gt;
  
  
  Deploy with Docker Swarm
&lt;/h2&gt;

&lt;p&gt;Welcome to Day 28 👋 ! Your app has become an overnight success. Everyone is using your app, from celebrities to your friends. You never anticipated this and found yourself in a situation where your app isn't able to keep up with the overwhelming number of requests. Fret not! Appwrite was designed with exactly this in mind. As you already know, Appwrite is designed as a set of stateless microservices with scalability as one of our top priorities! While there are many ways to achieve scalability with lots of orchestration services, we will take a look at one of the most intuitive ones. Today, we're going to discuss horizontally scaling Appwrite with Docker Swarm.&lt;/p&gt;

&lt;h2&gt;
  
  
  What is Docker Swarm?
&lt;/h2&gt;

&lt;p&gt;Docker Swarm is a container orchestration tool built right into the Docker CLI, which allows us to deploy our Docker services to a cluster of hosts instead of just the one allowed with &lt;a href="https://docs.docker.com/compose/"&gt;Docker Compose&lt;/a&gt;. This is known as Swarm Mode, not to be confused with the classic Docker Swarm that is &lt;a href="https://github.com/docker/classicswarm"&gt;no longer being developed&lt;/a&gt; as a standalone product. Docker Swarm works great with Appwrite as it builds upon the &lt;a href="https://docs.docker.com/compose/compose-file/"&gt;Compose specification&lt;/a&gt;, meaning we can use Appwrite's &lt;code&gt;docker-compose&lt;/code&gt; configuration to deploy to a swarm (with a few changes here and there). Its simplicity allows us to get started right away!&lt;/p&gt;

&lt;h2&gt;
  
  
  Deploying Appwrite with Swarm
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Prerequisites
&lt;/h3&gt;

&lt;p&gt;For this example, we'll need the following:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://docs.docker.com/get-docker/"&gt;Docker is installed&lt;/a&gt; on each of your hosts.&lt;/li&gt;
&lt;li&gt;The following ports must be open between your hosts:

&lt;ul&gt;
&lt;li&gt;TCP port 2377 for cluster management communications&lt;/li&gt;
&lt;li&gt;TCP and UDP port 7946 for communication among nodes&lt;/li&gt;
&lt;li&gt;UDP port 4789 for overlay network traffic&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;
&lt;li&gt;The "leader" server has Appwrite's &lt;a href="https://gist.github.com/eldadfux/977869ff6bdd7312adfd4e629ee15cc5"&gt;Compose files&lt;/a&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Creating the Swarm
&lt;/h3&gt;

&lt;p&gt;We'll create the swarm on whichever host we want to be the "leader." Initialize the swarm with:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;docker swarm init
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Which should output:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Swarm initialized: current node (7db8w7aurb7qrhvm0c0ttd4ky) is now a manager.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;To add a worker to this swarm, run the following command:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;docker swarm &lt;span class="nb"&gt;join&lt;/span&gt; &lt;span class="nt"&gt;--token&lt;/span&gt; SWMTKN-1-0wagrl3qt4loflf9jcadj8gx53fj2dzmbwaato7r50vghmgiwp-cvo3jflyfh2gnu46pzjtaexv2 your.ip.addr.ess:2377
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Which should output:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;To add a manager to this swarm, run 'docker swarm join-token manager' and follow the instructions.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now, let's run the provided command on our other system(s) - we're looking for the message &lt;code&gt;This node joined a swarm as a worker.&lt;/code&gt; Once that's complete, we can go back to the "leader" host and can see both systems with:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;docker node &lt;span class="nb"&gt;ls&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Which should display the following:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;ID                            HOSTNAME          STATUS    AVAILABILITY   MANAGER STATUS   ENGINE VERSION
yfl7xsy5birfbpiw040chef67     appwrite          Ready     Active                          20.10.6
op3nf4ab6f5v1lulwkpyy2a83 *   appwrite_leader   Ready     Active         Leader           20.10.6
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Update &lt;code&gt;docker-compose.yml&lt;/code&gt;
&lt;/h3&gt;

&lt;p&gt;Now that the swarm is ready, we'll need to make some changes to &lt;code&gt;docker-compose.yml&lt;/code&gt; to make it Swarm-compatible.&lt;/p&gt;

&lt;p&gt;Volumes in a Docker swarm aren't shared between hosts by default, so we'll use NFS to share directories between the hosts. Shared data can be accomplished in a variety of ways, but this is the simplest to get started. To do so, we'll replace all the named volumes with NFS mounts. DigitalOcean has a &lt;a href="https://www.digitalocean.com/community/tutorials/how-to-set-up-an-nfs-mount-on-ubuntu-20-04"&gt;great guide&lt;/a&gt; on configuring NFS, so refer to that guide for more details.&lt;/p&gt;

&lt;p&gt;We're going to configure these NFS volumes on our "leader" host and share those folders with other hosts in the swarm. We'll use the following directories to replace the Docker volumes and share via NFS:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;mkdir&lt;/span&gt; &lt;span class="nt"&gt;-p&lt;/span&gt; /nfs/&lt;span class="o"&gt;{&lt;/span&gt;mariadb,redis,cache,uploads,certificates,functions,influxdb,config&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Next, we'll create the corresponding &lt;code&gt;/nfs&lt;/code&gt; directories on the second host (with the same command as above), where we'll mount the NFS share from the "leader" host.&lt;/p&gt;

&lt;p&gt;Now, replace each named volume in &lt;code&gt;docker-compose.yml&lt;/code&gt; with its corresponding NFS directory:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# - appwrite-uploads:/storage/uploads:rw&lt;/span&gt;
- /nfs/uploads:/storage/uploads:rw

&lt;span class="c"&gt;# - appwrite-certificates:/storage/certificates:rw&lt;/span&gt;
- /nfs/certificates:/storage/certificates:rw

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then, we'll need to remove the &lt;code&gt;depends_on&lt;/code&gt; and &lt;code&gt;container_name&lt;/code&gt; stanzas from &lt;code&gt;docker-compose.yml&lt;/code&gt;, as they aren't supported by Docker Swarm.&lt;/p&gt;

&lt;h3&gt;
  
  
  Overlay Networks
&lt;/h3&gt;

&lt;p&gt;Docker uses &lt;a href="https://docs.docker.com/network/overlay/"&gt;overlay networks&lt;/a&gt; to connect each node together in the swarm, so containers can communicate with each other regardless of where it is deployed. We could create the overlay network with the Docker CLI, but instead, let's capture this change in &lt;code&gt;docker-compose.yml&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;networks:
  gateway:
  appwrite:
    driver: overlay
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Ready to Deploy
&lt;/h3&gt;

&lt;p&gt;Once everything is in place, we'll set our &lt;a href="https://appwrite.io/docs/environment-variables"&gt;Appwrite environment variables&lt;/a&gt; and deploy them to the swarm with:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;docker stack deploy &lt;span class="nt"&gt;-c&lt;/span&gt; &amp;lt;&lt;span class="o"&gt;(&lt;/span&gt;docker-compose config&lt;span class="o"&gt;)&lt;/span&gt; appwrite
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;If you see &lt;code&gt;docker-compose config&lt;/code&gt; warnings, try upgrading the Compose version to &lt;code&gt;version: '3.8'&lt;/code&gt; at the head of &lt;code&gt;docker-compose.yml&lt;/code&gt; to utilize the latest Compose specification.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Our microservice workers rely on Redis to handle pub/sub, so you may see them restart until the stack self-heals. Once everything is deployed, you can check the status of the services with:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;docker service &lt;span class="nb"&gt;ls
&lt;/span&gt;ID             NAME                                    MODE         REPLICAS   IMAGE                     PORTS
ktfto6dap451   appwrite_appwrite                       replicated   1/1        appwrite/appwrite:0.8.0   
hazw2csk4epd   appwrite_appwrite-maintenance           replicated   1/1        appwrite/appwrite:0.8.0   
fshro0zn8iw6   appwrite_appwrite-schedule              replicated   1/1        appwrite/appwrite:0.8.0   
jep5n0gnmvy6   appwrite_appwrite-worker-audits         replicated   1/1        appwrite/appwrite:0.8.0   
oiftp636aq6v   appwrite_appwrite-worker-certificates   replicated   1/1        appwrite/appwrite:0.8.0   
tlu7yxvtrr0r   appwrite_appwrite-worker-deletes        replicated   1/1        appwrite/appwrite:0.8.0   
rda2kspenbzr   appwrite_appwrite-worker-functions      replicated   1/1        appwrite/appwrite:0.8.0   
im800v9tct4n   appwrite_appwrite-worker-mails          replicated   1/1        appwrite/appwrite:0.8.0   
ry0u3v726o8h   appwrite_appwrite-worker-tasks          replicated   1/1        appwrite/appwrite:0.8.0   
734y2mr6gzkc   appwrite_appwrite-worker-usage          replicated   1/1        appwrite/appwrite:0.8.0   
bkotuk5kwmxx   appwrite_appwrite-worker-webhooks       replicated   1/1        appwrite/appwrite:0.8.0   
ff6iicbmf5my   appwrite_influxdb                       replicated   1/1        appwrite/influxdb:1.0.0   
892923vq96on   appwrite_mariadb                        replicated   1/1        appwrite/mariadb:1.2.0    
uw3l8bkoc3sl   appwrite_redis                          replicated   1/1        redis:6.0-alpine3.12      
ulp1cy06plnv   appwrite_telegraf                       replicated   1/1        appwrite/telegraf:1.0.0   
9aswnz3qq693   appwrite_traefik                        replicated   1/1        traefik:2.3               &lt;span class="k"&gt;*&lt;/span&gt;:80-&amp;gt;80/tcp, &lt;span class="k"&gt;*&lt;/span&gt;:443-&amp;gt;443/tcp
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;I've included my completed Compose file in a &lt;a href="https://gist.github.com/kodumbeats/5f2a52297bbc0edb04385bdd43083d7d"&gt;GitHub gist&lt;/a&gt; for reference.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Configuration
&lt;/h2&gt;

&lt;p&gt;Docker Swarm has a lot of configuration options available, so we won't cover everything here. Instead, let's talk about some of the most useful stanzas when configuring your deployment.&lt;/p&gt;

&lt;h3&gt;
  
  
  Replicas
&lt;/h3&gt;

&lt;p&gt;Since Appwrite is largely stateless, you can scale each service up or down individually, depending on your app's needs. For example, we may want to have two Functions workers so we can handle twice as many function executions:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;deploy:
  replicas: 1
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We can check that the replica was deployed by filtering for the specific service:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;docker service &lt;span class="nb"&gt;ls&lt;/span&gt; &lt;span class="nt"&gt;--filter&lt;/span&gt; &lt;span class="nv"&gt;name&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;appwrite_appwrite-worker-functions 
ID             NAME                                 MODE         REPLICAS   IMAGE                     PORTS 
rda2kspenbzr   appwrite_appwrite-worker-functions   replicated   2/2        appwrite/appwrite:0.8.0
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Node Constraints
&lt;/h3&gt;

&lt;p&gt;Docker Swarm allows us to control where containers deploy in the swarm using placement constraints. For example, we could configure Traefik or MariaDB to just reside on a manager node with the following added to &lt;code&gt;docker-compose.yml&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;deploy:
  placement:
    constraints: [node.role == manager]
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  What's Next
&lt;/h2&gt;

&lt;p&gt;We just covered the tip of the iceberg. For further reading on running Appwrite in a Docker Swarm:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Docker's &lt;a href="https://docs.docker.com/engine/swarm/admin_guide/"&gt;admin guide&lt;/a&gt; has a lot of extra information about how to manage nodes in a swarm and some considerations for production.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://docs.docker.com/engine/swarm/secrets/"&gt;Docker secrets&lt;/a&gt; and &lt;a href="https://docs.docker.com/engine/swarm/configs/"&gt;Docker configs&lt;/a&gt; can be used to more easily control and distribute sensitive data through the swarm.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Credits
&lt;/h2&gt;

&lt;p&gt;We hope you liked this write-up. You can follow &lt;a href="https://twitter.com/search?q=%2330daysofappwrite"&gt;#30DaysOfAppwrite&lt;/a&gt; on Social Media to keep up with all of our posts. The complete event timeline can be found &lt;a href="http://30days.appwrite.io"&gt;here&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://appwrite.io/discord"&gt;Discord Server&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://appwrite.io/"&gt;Appwrite Homepage&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/appwrite"&gt;Appwrite's Github&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Feel free to reach out to us on Discord if you would like to learn more about Appwrite, Aliens, or Unicorns 🦄. Stay tuned for tomorrow's article! Until then 👋&lt;/p&gt;

</description>
      <category>javascript</category>
      <category>webdev</category>
      <category>flutter</category>
      <category>30daysofappwrite</category>
    </item>
    <item>
      <title>#30DaysOfAppwrite : Appwrite for Production</title>
      <dc:creator>kodumbeats</dc:creator>
      <pubDate>Thu, 27 May 2021 12:38:54 +0000</pubDate>
      <link>https://dev.to/appwrite/30daysofappwrite-appwrite-for-production-56hi</link>
      <guid>https://dev.to/appwrite/30daysofappwrite-appwrite-for-production-56hi</guid>
      <description>&lt;h2&gt;
  
  
  Intro
&lt;/h2&gt;

&lt;p&gt;Appwrite is an open-source, self-hosted Backend-as-a-Service that makes app development &lt;strong&gt;easier&lt;/strong&gt; with a suite of SDKs and APIs to accelerate app development. &lt;a href="http://30days.appwrite.io/"&gt;#30DaysOfAppwrite&lt;/a&gt; is a month-long event focused on giving developers a walkthrough of all of Appwrite's features, starting from the basics to more advanced features like Cloud Functions! Alongside we will also be building a fully-featured Medium clone to demonstrate how these concepts can be applied when building a real-world app. We also have some exciting prizes for developers who follow along with us!&lt;/p&gt;

&lt;h2&gt;
  
  
  Appwrite for Production
&lt;/h2&gt;

&lt;p&gt;Welcome to Day 27 👋. Now that we've covered many of the capabilities of Appwrite, we should discuss running Appwrite in production once your app is finally ready for users.&lt;/p&gt;

&lt;p&gt;First and foremost, good security is a moving target. Appwrite provides a suite of APIs that abstracts many security requirements of your application, but hosting software online means exposing a computer to the internet. While we can't cover everything, let's discuss some security best practices when running Appwrite in production.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Server
&lt;/h2&gt;

&lt;p&gt;Before discussing the steps to run Appwrite in production, we need to talk about the &lt;em&gt;system&lt;/em&gt; on which Appwrite will run. These tips assume you're running Appwrite on a Linux-based server, but the principles apply to any operating system.&lt;/p&gt;

&lt;h3&gt;
  
  
  Updates
&lt;/h3&gt;

&lt;p&gt;Most security breaches occur on systems that run out-of-date software versions with security vulnerabilities. The problem is understandable - it's hard to keep up with system updates. Running updates on a &lt;a href="https://man7.org/linux/man-pages/man5/crontab.5.html"&gt;cron&lt;/a&gt; schedule isn't the best either, as security updates are best installed immediately. Use tools like Ubuntu's &lt;a href="https://help.ubuntu.com/community/AutomaticSecurityUpdates"&gt;&lt;code&gt;unattended-upgrades&lt;/code&gt;&lt;/a&gt; and Fedora's &lt;a href="https://fedoraproject.org/wiki/AutoUpdates"&gt;&lt;code&gt;dnf-automatic&lt;/code&gt;&lt;/a&gt; packages to run with the latest updates for your software.&lt;/p&gt;

&lt;h3&gt;
  
  
  Firewall and SSH
&lt;/h3&gt;

&lt;p&gt;A security best practice is a deny-by-default security policy - we should only give explicit access to the services we want. Appwrite considers this in its default configuration: the only service exposed to the outside world is what we need, the &lt;a href="https://traefik.io/traefik/"&gt;Traefik&lt;/a&gt; proxy. So, if Appwrite is the only service we want to expose on the server publicly, we can use firewall tools to block access to any other unused ports.&lt;/p&gt;

&lt;p&gt;If you use SSH to administer your system, don't forget to leave that open in your firewall! SSH is considered a private service, meaning that it should be publicly accessible, but only to authorized accounts. The best practice is to use cryptographic tools like &lt;a href="https://www.digitalocean.com/community/tutorials/ssh-essentials-working-with-ssh-servers-clients-and-keys"&gt;SSH keys&lt;/a&gt; instead of passwords, as they're much, much harder to falsify.&lt;/p&gt;

&lt;h3&gt;
  
  
  More Reading
&lt;/h3&gt;

&lt;p&gt;Here are some additional resources that go into more detail about best practices:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://docs.docker.com/engine/security/"&gt;Docker security&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.digitalocean.com/community/tutorials/recommended-security-measures-to-protect-your-servers"&gt;DigitalOcean Recommended Security Measures&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Securing Appwrite
&lt;/h2&gt;

&lt;p&gt;Now, let's discuss setting up Appwrite for production.&lt;/p&gt;

&lt;h3&gt;
  
  
  Environment Variables
&lt;/h3&gt;

&lt;p&gt;You can easily configure Appwrite for production with the many environment variables that it offers. The following variables should be set in the hidden &lt;code&gt;.env&lt;/code&gt; file in your &lt;code&gt;appwrite&lt;/code&gt; installation directory when deploying for production:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;_APP_ENV&lt;/code&gt;: Change to &lt;code&gt;production&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;_APP_OPTIONS_ABUSE&lt;/code&gt;: Enables abuse checks and rate-limiting for the API. Set to &lt;code&gt;enabled&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;_APP_OPTIONS_FORCE_HTTPS&lt;/code&gt;: Forces connections to use HTTPS for secure data transfer. Set to &lt;code&gt;enabled&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;_APP_OPENSSL_KEY_V1&lt;/code&gt;: This is the secret used to encrypt information like sessions and passwords. Please change this to something secure and random, and &lt;strong&gt;keep it safe and backed up&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;_APP_DOMAIN&lt;/code&gt;: Set this to &lt;a href="https://appwrite.io/docs/custom-domains"&gt;your domain name&lt;/a&gt; for Appwrite to auto-generate an SSL certificate.&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  Restrict Console Access
&lt;/h4&gt;

&lt;p&gt;Three environment variables are available to restrict access to the Appwrite console:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;code&gt;_APP_CONSOLE_WHITELIST_EMAILS&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;_APP_CONSOLE_WHITELIST_IPS&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;_APP_CONSOLE_WHITELIST_ROOT&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Set the &lt;code&gt;_ROOT&lt;/code&gt; var to &lt;code&gt;enabled&lt;/code&gt; if you only want a single account to have access to the console. You can restrict access to specific email and IP addresses with their respective environment variables for multiple users.&lt;/p&gt;

&lt;h4&gt;
  
  
  Antivirus
&lt;/h4&gt;

&lt;p&gt;For production, you can enable &lt;code&gt;clamav&lt;/code&gt; scanning of uploaded files for any known malicious objects. Set &lt;code&gt;_APP_STORAGE_ANTIVIRUS&lt;/code&gt; to &lt;code&gt;enabled&lt;/code&gt; and &lt;a href="https://github.com/appwrite/appwrite/blob/master/docker-compose.yml#L417-L423"&gt;uncomment the service&lt;/a&gt; in &lt;code&gt;docker-compose.yml&lt;/code&gt; to use this feature. Don't forget to also uncomment &lt;code&gt;clamav&lt;/code&gt; in the &lt;a href="https://github.com/appwrite/appwrite/blob/master/docker-compose.yml#L74"&gt;&lt;code&gt;depends_on&lt;/code&gt; section&lt;/a&gt; of the main &lt;code&gt;appwrite&lt;/code&gt; service. &lt;/p&gt;

&lt;h4&gt;
  
  
  Functions
&lt;/h4&gt;

&lt;p&gt;Cloud Functions can be customized to suit the needs of your production system, largely for controlling resources available to Function executions:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;_APP_FUNCTIONS_CPUS&lt;/code&gt;: The maximum number of CPU cores that Cloud Functions can use.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;_APP_FUNCTIONS_MEMORY&lt;/code&gt;: The maximum memory available to Cloud Functions (in megabytes).&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;_APP_FUNCTIONS_CONTAINERS&lt;/code&gt;: The maximum number of containers Appwrite keeps alive defaults to 10. Increase this number to increase the number of warm functions.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;_APP_FUNCTIONS_RUNTIMES&lt;/code&gt;: A list of available runtimes for new Cloud Functions.&lt;/li&gt;
&lt;/ul&gt;

&lt;blockquote&gt;
&lt;p&gt;All Appwrite environment variables can be found in our &lt;a href="https://appwrite.io/docs/environment-variables"&gt;docs&lt;/a&gt;.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Credits
&lt;/h2&gt;

&lt;p&gt;We hope you liked this write-up. You can follow &lt;a href="https://twitter.com/search?q=%2330daysofappwrite"&gt;#30DaysOfAppwrite&lt;/a&gt; on Social Media to keep up with all of our posts. The complete event timeline can be found &lt;a href="http://30days.appwrite.io"&gt;here&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://appwrite.io/discord"&gt;Discord Server&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://appwrite.io/"&gt;Appwrite Homepage&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/appwrite"&gt;Appwrite's Github&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Feel free to reach out to us on Discord if you would like to learn more about Appwrite, Aliens, or Unicorns 🦄. Stay tuned for tomorrow's article! Until then 👋&lt;/p&gt;

</description>
      <category>javascript</category>
      <category>webdev</category>
      <category>flutter</category>
      <category>30daysofappwrite</category>
    </item>
    <item>
      <title>Appwrite 0.8: ARM Support</title>
      <dc:creator>kodumbeats</dc:creator>
      <pubDate>Sat, 22 May 2021 06:27:38 +0000</pubDate>
      <link>https://dev.to/appwrite/appwrite-0-8-arm-support-59bc</link>
      <guid>https://dev.to/appwrite/appwrite-0-8-arm-support-59bc</guid>
      <description>&lt;p&gt;Appwrite 0.8 brings support for ARM64 processors - you can now install Appwrite on Amazon's &lt;strong&gt;Graviton2&lt;/strong&gt; instances, &lt;strong&gt;Apple M1&lt;/strong&gt; systems (without Rosetta 2), Raspberry Pi 4 SoCs, or any other 64-bit ARM device! To appreciate ARM's position in today's computing, let's take a brief tour of the history of CPU architectures. &lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Appwrite is an open-source, self-hosted Backend-as-a-Service that aims to make app development &lt;strong&gt;easier&lt;/strong&gt; with SDKs available in a variety of programming languages. We love chatting about Appwrite, Aliens 👽 or Unicorns 🦄 over at &lt;a href="https://appwrite.io/discord"&gt;Discord&lt;/a&gt;.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Beginning with the 8086
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ffvn9jvevyf2tp96hq4nc.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ffvn9jvevyf2tp96hq4nc.jpg" alt="Alt Text" width="800" height="533"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Photo by Thomas Nguyen - &lt;a href="https://commons.wikimedia.org/w/index.php?curid=46809082"&gt;Own work&lt;/a&gt;, CC BY-SA 4.0, &lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;The Intel 8086 processor was released in 1978 and was carried into households with the widespread success of the IBM 5150 Personal Computer, &lt;strong&gt;the&lt;/strong&gt; PC. Intel then built on the success of the 8086 with following processors: the 80286, 80386, 80486, and more, all the way through Pentium and beyond. The set of instructions used to command these processors, known now as "x86", is still supported on chips today - any assembly program written for the 8086 will run out-of-the-box on modern Intel processors, albeit much, &lt;em&gt;much&lt;/em&gt;, &lt;strong&gt;much&lt;/strong&gt; faster.  &lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Ever wonder how AMD is able to make x86-compatible processors without lawsuits from Intel? The legal landscape around the x86 architecture is fascinating - check out &lt;a href="https://jolt.law.harvard.edu/digest/intel-and-the-x86-architecture-a-legal-perspective"&gt;this commentary&lt;/a&gt; from Harvard Law to learn more.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;The first "x86" instruction sets supported very basic processor-level operations: reading/writing from memory, basic arithmetic, and control flow logic, to name a few. To meet ever-growing computing demands, Intel needed to expand the x86 instruction set to handle more complex operations like handling memory in chunks, complicated maths like square root, logarithms, and trigonometry, and more. While the instruction set grew, so too did the power requirements. The computing industry was fine with power consumption, so long as their computers ran faster, that is, until power consumption mattered - the era of smartphones.  &lt;/p&gt;

&lt;h2&gt;
  
  
  The Tale of Two ARMs
&lt;/h2&gt;

&lt;p&gt;Smartphones require a specific balance of power consumption and performance, and x86 processors didn't fit the bill - the complex x86 instructions required extra electricity, logic gates, and silicon surface area, and mobile computing had opposite requirements. RISC (Reduced Instruction Set Computers) processors took a more specialized approach: only include the basic instructions required for a modern computer, and make those instructions &lt;em&gt;highly optimized&lt;/em&gt;. &lt;/p&gt;

&lt;p&gt;ARM, an English semiconductor company, designs RISC instruction sets and licenses them to manufacturers to handle production.You probably recognize a few of these manufactors: Samsung, Broadcom, Qualcomm, and NVidia, to name a few. These companies handle the manufacturing and distribution of ARM-based systems, including smartphones, tablets, smart TVs, washing machines, cars, printers, and so much more. &lt;/p&gt;

&lt;p&gt;Low-power processors aren't just for mobile/IoT devices anymore, nor are they less capable than x86 computers. Most notably, the Apple M1 (ARM-based) has made a big splash with ARM now powering iPads, Macbooks, Mac Minis, and now iMacs, with other manufacturers set to follow in their footsteps. Amazon has also been a pioneer of ARM in the datacenter - Amazon employs a 64-core(!) Neoverse N1 ARM processor in their &lt;a href="https://aws.amazon.com/ec2/graviton/"&gt;Graviton2&lt;/a&gt; virtual servers.&lt;/p&gt;

&lt;h2&gt;
  
  
  What's Next?
&lt;/h2&gt;

&lt;p&gt;You can get started with your favorite 64-bit ARM device now - follow the &lt;a href="https://appwrite.io/docs/installation"&gt;installation instructions&lt;/a&gt; to get started. The Appwrite community is very excited about Appwrite apps which are now possible thanks to Appwrite on RPi (especially me), and we've installed it on a variety of operating systems: PiOS, Ubuntu, and BalenaOS. You can see Appwrite running on a Raspberry Pi 4 2GB with Ubuntu 20.04:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fmd3tuuj5xehlsps14bhu.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fmd3tuuj5xehlsps14bhu.png" alt="Alt Text" width="800" height="491"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;What are you most excited to build? Do you have any homelab projects which just became easier thanks to Appwrite on ARM? Let us know on &lt;a href="https://appwrite.io/discord"&gt;Discord&lt;/a&gt;, &lt;a href="https://twitter.com/appwrite_io"&gt;Twitter&lt;/a&gt;, &lt;a href="https://dev.to/appwrite"&gt;Dev.to&lt;/a&gt;, or anywhere you find a friendly Appwriter. :) Also, the &lt;a href="https://github.com/appwrite/awesome-appwrite"&gt;awesome-appwrite&lt;/a&gt; repo keeps growing with new tutorials, demos, videos, and more!&lt;/p&gt;

</description>
      <category>opensource</category>
      <category>raspberrypi</category>
      <category>serverless</category>
      <category>architecture</category>
    </item>
    <item>
      <title>Announcing Appwrite 0.8 - an open-source, self-hosted BaaS</title>
      <dc:creator>kodumbeats</dc:creator>
      <pubDate>Wed, 19 May 2021 16:11:20 +0000</pubDate>
      <link>https://dev.to/appwrite/announcing-appwrite-0-8-an-open-source-self-hosted-baas-kda</link>
      <guid>https://dev.to/appwrite/announcing-appwrite-0-8-an-open-source-self-hosted-baas-kda</guid>
      <description>&lt;p&gt;We're incredibly excited to announce the release of Appwrite 0.8, packed with a ton of cool new features like &lt;strong&gt;JWT support&lt;/strong&gt;, &lt;strong&gt;ARM support&lt;/strong&gt;, &lt;strong&gt;Anonymous Login&lt;/strong&gt;, and more! Last month, we gave a &lt;a href="https://medium.com/appwrite-io/appwrite-0-8-is-coming-soon-and-this-is-what-you-can-expect-fa8cbed1c0eb"&gt;sneak peek&lt;/a&gt; of some of the changes, and we're back today to keep you waiting no longer. Let's dive in! 🤿&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Appwrite is an open-source, self-hosted Backend-as-a-Service that aims to make app development &lt;strong&gt;easier&lt;/strong&gt; with SDKs available in a variety of programming languages. Come hang out with us on &lt;a href="https://appwrite.io/discord"&gt;Discord&lt;/a&gt;.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Anonymous Login and JWT 🔐
&lt;/h2&gt;

&lt;p&gt;Not every app needs users to create an account right away. With &lt;strong&gt;Anonymous Login&lt;/strong&gt;, save sessions without asking for email addresses, and convert those users to registered accounts later with ease. The implementation is just like creating a normal user session via the &lt;a href="https://appwrite.io/docs/client/account?sdk=web#accountCreateSession"&gt;&lt;code&gt;createSession&lt;/code&gt;&lt;/a&gt; method:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;sdk&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Appwrite&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

&lt;span class="nx"&gt;sdk&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;setEndpoint&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;https://[HOSTNAME_OR_IP]/v1&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="c1"&gt;// Your API Endpoint&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;setProject&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;5df5acd0d48c2&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="c1"&gt;// Your project ID&lt;/span&gt;
&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;promise&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;sdk&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;account&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;createAnonymousSession&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

&lt;span class="nx"&gt;promise&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;then&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;function &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;response&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;response&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// Success&lt;/span&gt;
&lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="nf"&gt;function &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// Failure&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Also, if you've ever needed to act as a user from a &lt;a href="https://appwrite.io/docs/sdks"&gt;server SDK&lt;/a&gt;, Appwrite now supports authentication via JSON Web Tokens (&lt;a href="https://jwt.io/"&gt;JWT&lt;/a&gt;). This change allows Appwrite to work with the server-side rendering capabilities of frameworks like &lt;a href="https://nextjs.org/"&gt;Next.js&lt;/a&gt;, &lt;a href="https://nuxtjs.org/"&gt;Nuxt.js&lt;/a&gt;, and &lt;a href="https://www.gatsbyjs.com/"&gt;Gatsby.js&lt;/a&gt;, as well as unlock user actions from server-side SDKs.&lt;/p&gt;

&lt;p&gt;First, a JWT is created for the user from a Client SDK:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;appwrite&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;account&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;createJWT&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;then&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;function &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;response&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;response&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="nf"&gt;function &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then, the JWT is used to act on behalf of the user server-side:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;sdk&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;node-appwrite&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;client&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nx"&gt;sdk&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;Client&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

&lt;span class="nx"&gt;client&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;setEndpoint&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;https://[HOSTNAME_OR_IP]/v1&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="c1"&gt;// Your API Endpoint&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;setProject&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;5df5acd0d48c2&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="c1"&gt;// Your project ID&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;setJWT&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;919c2d18fb5d4...a2ae413da83346ad2&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="c1"&gt;// Your JWT&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  ARM Support 🦾
&lt;/h2&gt;

&lt;p&gt;The ARM ecosystem has been booming since Apple's M1 processors landed in their new lineup of devices. Starting with 0.8, install Appwrite on your favorite 64-bit ARM device, from Amazon Graviton2 down to the Raspberry Pi 4! [1] ARM support falls in line with our mission to make Appwrite &lt;strong&gt;technology agnostic&lt;/strong&gt;, and we're excited to hear all of the new places where Appwrite can run. &lt;/p&gt;

&lt;p&gt;To celebrate this milestone, we have ARM systems to give away as a part of &lt;a href="https://30days.appwrite.io/"&gt;#30DaysofAppwrite&lt;/a&gt;! 🥳 Through the month of May, we're building a Medium.com blog clone to demonstrate how &lt;strong&gt;easy&lt;/strong&gt; the developer experience is with Appwrite, and we invite you to build alongside us. Eligible submissions get some cool 😎 swag, and the best projects will receive Raspberry Pi 4 development kits. 😍&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;[1] For both Graviton2 servers and Raspberry Pis, we recommend at least 2GB of RAM for the best Appwrite experience.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Control your Console 🖥️
&lt;/h2&gt;

&lt;p&gt;We've updated the console with a few new goodies. First, if you enable the new "root" account setting, only a single admin account can be created on your Appwrite server. If you need to share access to the Appwrite console, you can restrict account creation to specific IP addresses with the &lt;code&gt;_APP_CONSOLE_WHITELIST_IPS&lt;/code&gt; environment variable. &lt;/p&gt;

&lt;p&gt;Additionally, Appwrite 0.8 brings new settings to users - now, you can choose which of our growing authentication methods you'd like to use for your apps: email/password login, anonymous login, JWT auth, and more! &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fhl8sa1dyish9bkx0d7hn.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fhl8sa1dyish9bkx0d7hn.png" alt="Control Auth Methods" width="800" height="450"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  New Cloud Function Runtimes 🏃
&lt;/h2&gt;

&lt;p&gt;Appwrite 0.8 introduces &lt;strong&gt;Python 3.9&lt;/strong&gt;, &lt;strong&gt;Deno 1.8&lt;/strong&gt;, and &lt;strong&gt;Dart 2.12&lt;/strong&gt; as new runtimes for Cloud Functions. Upgrade existing functions or write new ones! If you're using Cloud Functions in a cool way, let us know on &lt;a href="https://appwrite.io/discord"&gt;Discord&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Slimmer and Faster ⏩
&lt;/h2&gt;

&lt;p&gt;You'll notice Appwrite 0.8 is a bit slimmer on system resources out-of-the-box. We found that the SMTP and antivirus services weren't helping new developers, so we've toggled off ClamAV and the included SMTP server for development. Because of these changes, we have been able to reduce our minimum requirements to &lt;strong&gt;1GB of RAM&lt;/strong&gt; (though we recommend 2GB for the better experience).&lt;/p&gt;

&lt;p&gt;We also updated our codebase to take advantage of the increased performance of some of our under the hood technologies. Based on our testing, we're seeing improved performance of about 8% compared to previous Appwrite versions 🚀&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fpgfyhk1szev9gyew9gxg.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fpgfyhk1szev9gyew9gxg.png" alt="Benchmarks" width="800" height="595"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Breaking Changes ⚒️
&lt;/h2&gt;

&lt;p&gt;Before you upgrade your Appwrite server to 0.8, check out the breaking changes that were introduced to see if you need to update any code.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The &lt;a href="https://appwrite.io/docs/server/users#usersDeleteUser"&gt;&lt;code&gt;deleteUser&lt;/code&gt; method&lt;/a&gt; in the Users API has been renamed to &lt;code&gt;delete&lt;/code&gt; to remain consistent with the rest of the API.&lt;/li&gt;
&lt;li&gt;Only logged in users &lt;a href="https://appwrite.io/docs/client/account?sdk=web#accountCreateSession"&gt;with active sessions&lt;/a&gt; can execute functions. If your app relies on this behavior, check out Anonymous Login.&lt;/li&gt;
&lt;li&gt;Only the user who &lt;a href="https://appwrite.io/docs/client/functions?sdk=web#functionsCreateExecution"&gt;triggers an execution&lt;/a&gt; gets access to the relevant execution logs.&lt;/li&gt;
&lt;li&gt;The &lt;a href="https://appwrite.io/docs/client/teams?sdk=web#teamsCreateMembership"&gt;&lt;code&gt;createMembership&lt;/code&gt; method&lt;/a&gt; has a new rate limit of 10 requests per 60 minutes per IP address.&lt;/li&gt;
&lt;li&gt;The &lt;a href="https://appwrite.io/docs/environment-variables"&gt;environment variable&lt;/a&gt; &lt;code&gt;_APP_FUNCTIONS_ENVS&lt;/code&gt; has been renamed to &lt;code&gt;APP_FUNCTIONS_RUNTIMES&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Several function execution environment variables have been renamed:

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;APPWRITE_FUNCTION_EVENT_PAYLOAD&lt;/code&gt; is now &lt;code&gt;APPWRITE_FUNCTION_EVENT_DATA&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;APPWRITE_FUNCTION_ENV_NAME&lt;/code&gt; is now &lt;code&gt;APPWRITE_FUNCTION_RUNTIME_NAME&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;APPWRITE_FUNCTION_ENV_VERSION&lt;/code&gt; is now &lt;code&gt;APPWRITE_FUNCTION_RUNTIME_VERSION&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  And More! 😍
&lt;/h2&gt;

&lt;p&gt;That's not all! To get all the details on Appwrite 0.8, check out all the changes in the &lt;a href="https://github.com/appwrite/appwrite/blob/master/CHANGES.md"&gt;changelog on GitHub&lt;/a&gt;. Are you curious about the big ideas we have up next, or have a great idea for Appwrite's future? Check out the &lt;a href="https://github.com/appwrite/rfc"&gt;RFC Repo&lt;/a&gt; for more details. Also, our &lt;a href="https://github.com/appwrite/awesome-appwrite"&gt;awesome-appwrite repo&lt;/a&gt; keeps growing with new tutorials, videos, and demos.&lt;/p&gt;

&lt;p&gt;If you've just discovered Appwrite and would like to get started, check out out our &lt;a href="https://30days.appwrite.io/"&gt;30 Days of Appwrite&lt;/a&gt; series where we explain step-by-step everything you need to know to build awesome Appwrite-powered apps. Follow us on &lt;a href="https://twitter.com/appwrite_io"&gt;Twitter&lt;/a&gt;, &lt;a href="https://dev.to/appwrite"&gt;Dev.to&lt;/a&gt;, or anywhere you find your friendly neighborhood Appwrite. &lt;/p&gt;

</description>
      <category>javascript</category>
      <category>flutter</category>
      <category>webdev</category>
      <category>news</category>
    </item>
    <item>
      <title>#30DaysofAppwrite: SSL Certificates</title>
      <dc:creator>kodumbeats</dc:creator>
      <pubDate>Thu, 06 May 2021 12:39:49 +0000</pubDate>
      <link>https://dev.to/appwrite/30daysofappwrite-ssl-certificates-c08</link>
      <guid>https://dev.to/appwrite/30daysofappwrite-ssl-certificates-c08</guid>
      <description>&lt;h2&gt;
  
  
  Intro
&lt;/h2&gt;

&lt;p&gt;Appwrite is an open-source, self-hosted Backend-as-a-Service that makes app development &lt;strong&gt;easier&lt;/strong&gt; with a suite of SDKs and APIs to accelerate app development. &lt;a href="http://30days.appwrite.io/" rel="noopener noreferrer"&gt;#30DaysOfAppwrite&lt;/a&gt; is a month-long event focused on giving developers a walkthrough of all of Appwrite's features, starting from the basics to more advanced features like cloud functions! Alongside we will also be building a full-featured Medium clone to demonstrate how these concepts can be applied when building a real-world app. We also have some exciting prizes for developers who follow along with us!&lt;/p&gt;

&lt;h2&gt;
  
  
  SSL Certificates in Appwrite
&lt;/h2&gt;

&lt;p&gt;Welcome to Day 6 👋 of &lt;code&gt;#30DaysofAppwrite&lt;/code&gt;. Today, we're going to discuss how to secure your Appwrite API traffic with SSL certificates: what they do, how to get them, and how to troubleshoot SSL problems in Appwrite.&lt;/p&gt;

&lt;h2&gt;
  
  
  What is SSL?
&lt;/h2&gt;

&lt;p&gt;SSL is a security protocol that cryptographically provides authentication for computers communicating with each other on the Internet, improved and later replaced by &lt;a href="https://developer.mozilla.org/en-US/docs/Glossary/TLS" rel="noopener noreferrer"&gt;TLS&lt;/a&gt; years ago. Despite TLS replacing SSL, both names are commonly used to refer to the same process: secure HTTP sessions with certificate keypairs (fancy text files) signed by a &lt;a href="https://developer.mozilla.org/en-US/docs/Glossary/Certificate_authority" rel="noopener noreferrer"&gt;Certificate Authority&lt;/a&gt;, CA for short. &lt;/p&gt;

&lt;h3&gt;
  
  
  Trusting Certificates
&lt;/h3&gt;

&lt;p&gt;The TLS protocol provides cryptographically unique keypairs that not only provide encryption, but also include domain, host, and organization information in the certificate. However, since TLS technology is &lt;a href="https://github.com/openssl/openssl" rel="noopener noreferrer"&gt;open-source&lt;/a&gt;, anyone can operate as a CA and sign certificates. To keep users secure, computers and browsers ship with lists of pre-vetted CAs to trust automatically[1]. Websites that use certificates issued by these trusted sources get the all-important lock🔒 next to their domain in the URL bar. Websites without them, however, face the dreaded &lt;code&gt;Warning: Potential Security Risk Ahead&lt;/code&gt;.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;[1] For the curious, here's Mozilla's list of &lt;a href="https://wiki.mozilla.org/CA/Included_Certificates" rel="noopener noreferrer"&gt;trusted sources&lt;/a&gt; for Firefox.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fpc4dhphr1ym63hyjtml1.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fpc4dhphr1ym63hyjtml1.png" alt="Self Signed Warning"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The process of becoming a universally trusted CA on these lists &lt;a href="https://en.wikipedia.org/wiki/Key_ceremony" rel="noopener noreferrer"&gt;can be costly&lt;/a&gt;, which is why organizations like IdenTrust and DigiCert charge money for their services. These companies have the resources and knowledge to provide a range of security guarantees, protecting financial institutions, governments, militaries, and more. Though, I'm assuming that you're not starting a bank, and don't have the funds to get a commercial SSL certificate. Where are the free options?&lt;/p&gt;

&lt;h3&gt;
  
  
  Welcome, Let's Encrypt
&lt;/h3&gt;

&lt;p&gt;Let's Encrypt is a free, automated, and trusted Certificate Authority that aims to provide for a safer, more secure Internet. Appwrite uses their popular &lt;a href="https://certbot.eff.org/" rel="noopener noreferrer"&gt;&lt;code&gt;certbot&lt;/code&gt;&lt;/a&gt; tool under the hood to automatically handle certificate generation and renewal, so you can focus on building your app. &lt;/p&gt;

&lt;h2&gt;
  
  
  Securing Appwrite with HTTPS
&lt;/h2&gt;

&lt;p&gt;To illustrate by example, let's assume I've installed Appwrite on a  VPS and bought the domain &lt;code&gt;example.com&lt;/code&gt; for my next Appwrite-powered project. What steps are necessary to serve my app on &lt;code&gt;example.com&lt;/code&gt;? &lt;/p&gt;

&lt;h3&gt;
  
  
  Domain records
&lt;/h3&gt;

&lt;p&gt;Your registrar ultimately has control over your domain (our &lt;code&gt;example.com&lt;/code&gt;), so we'll need to start there to point the domain at the IP address of your VPS. For this, we can use a DNS A record. Adding DNS records to your domain varies by registrar, so check out our docs on &lt;a href="https://appwrite.io/docs/custom-domains" rel="noopener noreferrer"&gt;Custom Domains&lt;/a&gt; for a bunch of helpful links and more specific instructions.&lt;/p&gt;

&lt;h3&gt;
  
  
  SSL Certificates in Development
&lt;/h3&gt;

&lt;p&gt;As mentioned before, all the required technology to generate your own SSL certificate is open-source, but it just isn't globally trusted by browsers. That's totally fine for development (assuming you trust yourself 😂) - Appwrite provides a self-signed certificate out-of-the-box (via the Traefik proxy), so your work is immediately encrypted. To do this, we need to let Appwrite know we're trying to use the self-signed certificate. Our SDKs all accept a &lt;code&gt;client.setSelfSigned()&lt;/code&gt; method to handle this. Here's an example using our &lt;a href="https://appwrite.io/docs/getting-started-for-web" rel="noopener noreferrer"&gt;Web SDK&lt;/a&gt;:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;

&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="nx"&gt;Appwrite&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;appwrite&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;client&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Appwrite&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

&lt;span class="nx"&gt;client&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;setEndpoint&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;https://example.com/v1&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;setProject&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;5df5acd0d48c2&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;setSelfSigned&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="p"&gt;;&lt;/span&gt;


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;h3&gt;
  
  
  SSL Certificates in Production
&lt;/h3&gt;

&lt;p&gt;Now, say you're past the development stage for &lt;code&gt;example.com&lt;/code&gt;, and you're ready to move to production. The following is required for Appwrite to issue a production-ready SSL certificate (with the lock🔒):&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Appwrite in &lt;code&gt;production&lt;/code&gt; mode via &lt;code&gt;_APP_ENV=production&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;A valid email set via &lt;code&gt;_APP_SYSTEM_SECURITY_EMAIL_ADDRESS&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;A public-facing domain set via &lt;code&gt;_APP_DOMAIN&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Traefik (proxy webserver) listening on port 80&lt;/li&gt;
&lt;li&gt;Remove references to &lt;code&gt;client.setSelfSigned&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;blockquote&gt;
&lt;p&gt;Our docs on &lt;a href="https://appwrite.io/docs/environment-variables" rel="noopener noreferrer"&gt;Appwrite environment variables&lt;/a&gt; are a good reference when changing Appwrite's configuration. &lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;To apply new environment variables, run:&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;

docker-compose up &lt;span class="nt"&gt;-d&lt;/span&gt;


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;This is where the Appwrite Certificates worker takes the reigns, calling &lt;code&gt;certbot&lt;/code&gt; to generate a certificate signed by Let's Encrypt. The worker then stores the certificates in a Docker volume for persistence and queues up a job to check the certificate renewal periodically (Let's Encrypt certificates are valid for 90 days by default).  &lt;/p&gt;

&lt;h2&gt;
  
  
  Debugging
&lt;/h2&gt;

&lt;p&gt;The first place to look for any certificate problems is the Certificates worker. You can check the service logs with:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;

docker-compose logs appwrite-worker-certificates


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;If you've configured your domain after your Appwrite server has started, you can re-trigger the Certificates worker by restarting Appwrite:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;

docker-compose restart appwrite


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;If you still can't figure it out, you can find help on &lt;a href="https://appwrite.io/discord" rel="noopener noreferrer"&gt;Discord&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Credits
&lt;/h2&gt;

&lt;p&gt;We hope you liked this write-up. You can follow &lt;a href="https://twitter.com/search?q=%2330daysofappwrite" rel="noopener noreferrer"&gt;#30DaysOfAppwrite&lt;/a&gt; on Social Media to keep up with all of our posts. The complete event timeline can be found &lt;a href="http://30days.appwrite.io" rel="noopener noreferrer"&gt;here&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://appwrite.io/discord" rel="noopener noreferrer"&gt;Discord Server&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://appwrite.io/" rel="noopener noreferrer"&gt;Appwrite Homepage&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/appwrite" rel="noopener noreferrer"&gt;Appwrite's Github&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Feel free to reach out to us on Discord if you would like to learn more about Appwrite, Aliens or Unicorns 🦄. Stay tuned for tomorrow's article! Until then 👋&lt;/p&gt;

</description>
    </item>
    <item>
      <title>Appwrite Releases Open Source Documentation</title>
      <dc:creator>kodumbeats</dc:creator>
      <pubDate>Wed, 10 Mar 2021 11:01:30 +0000</pubDate>
      <link>https://dev.to/appwrite/appwrite-releases-open-source-documentation-2d65</link>
      <guid>https://dev.to/appwrite/appwrite-releases-open-source-documentation-2d65</guid>
      <description>&lt;p&gt;At Appwrite, we're focused on creating the best developer experience possible, which is why we build tools that are &lt;strong&gt;easy to learn&lt;/strong&gt;. To that end, we're thrilled to announce that our &lt;a href="https://appwrite.io/docs"&gt;docs&lt;/a&gt; are now open-sourced, available on &lt;a href="https://github.com/appwrite/docs"&gt;GitHub&lt;/a&gt;!&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;We're building Appwrite, an open-source Backend-as-a-Service (BaaS), packaged as a set of Docker microservices, to give developers of any background all of the tools necessary to build a modern apps quickly and securely.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Docs as Code
&lt;/h2&gt;

&lt;p&gt;Appwrite uses the &lt;a href="https://github.com/utopia-php/framework"&gt;Utopia Framework&lt;/a&gt; under the hood, which encourages a declarative approach to building APIs. We explicitly declare route metadata - from labels to abuse limits to parameter definitions - &lt;strong&gt;as a part of our codebase&lt;/strong&gt;, allowing us to procedurally generate not only the &lt;a href="https://appwrite.io/specs/open-api3"&gt;API specification&lt;/a&gt;, but also &lt;a href="https://appwrite.io/docs/sdks"&gt;SDKs&lt;/a&gt; and code examples in multiple programming languages.&lt;/p&gt;

&lt;p&gt;For example, the parameter descriptions on the &lt;code&gt;listCollections&lt;/code&gt; method are used directly in the &lt;a href="https://appwrite.io/docs/server/database#databaseListCollections"&gt;endpoint documentation&lt;/a&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="nc"&gt;App&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'/v1/database/collections'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;desc&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'List Collections'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;label&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'sdk.method'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'listCollections'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;label&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'sdk.description'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'/docs/references/database/list-collections.md'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;param&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'search'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;''&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Text&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;256&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="s1"&gt;'Search term to filter your list results. Max length: 256 chars.'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;param&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'limit'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;25&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Range&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;100&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="s1"&gt;'Results limit value. By default will return maximum 25 results. Maximum of 100 results allowed per request.'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;param&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'offset'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Range&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;40000&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="s1"&gt;'Results offset. The default value is 0. Use this param to manage pagination.'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Our &lt;a href="https://github.com/appwrite/sdk-generator"&gt;SDK Generator&lt;/a&gt; does the heavy lifting of creating code examples for each API endpoint with &lt;a href="https://twig.symfony.com/"&gt;Twig&lt;/a&gt; templates. The above API route metadata creates the following Node.js code:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;sdk&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;node-appwrite&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="c1"&gt;// Init SDK&lt;/span&gt;
&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;client&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nx"&gt;sdk&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;Client&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;database&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nx"&gt;sdk&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;Database&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;client&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="nx"&gt;client&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;setEndpoint&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;https://[HOSTNAME_OR_IP]/v1&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="c1"&gt;// Your API Endpoint&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;setProject&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;5df5acd0d48c2&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="c1"&gt;// Your project ID&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;setKey&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;919c2d18fb5d4...a2ae413da83346ad2&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="c1"&gt;// Your secret API key&lt;/span&gt;
&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;promise&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;database&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;listCollections&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

&lt;span class="nx"&gt;promise&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;then&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;function &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;response&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;response&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="nf"&gt;function &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Better Together
&lt;/h2&gt;

&lt;p&gt;Appwrite is a remote-first, international team, so we appreciate the strength of diverse opinions. With open-source docs, our community can lend its wide expertise to help us improve any resource that lacks clarity, detail, or brevity (or has spelling mistakes). Development tools are only as strong as their technical documentation, and we've set out to make ours the best.&lt;/p&gt;

&lt;h2&gt;
  
  
  Getting Started
&lt;/h2&gt;

&lt;p&gt;If you're interested in improving Appwrite, check out the &lt;a href="https://github.com/appwrite/appwrite/blob/master/CONTRIBUTING.md#other-ways-to-help"&gt;contribution guide&lt;/a&gt; on GitHub. We're always happy to welcome new members to our growing Appwrite community.&lt;/p&gt;

&lt;h2&gt;
  
  
  Extra Reading
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://betterprogramming.pub/how-we-integrated-our-docs-and-sdks-as-first-class-citizens-of-our-coding-process-8e343def0e9"&gt;How We Integrated Our Docs and SDKs As First-Class Citizens of Our Coding Process&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://levelup.gitconnected.com/9-tips-that-will-help-you-write-a-winning-developers-documentation-for-your-next-project-d3248fcf704b"&gt;Your Docs Are a Gateway to Your Devtool&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>webdev</category>
      <category>opensource</category>
      <category>documentation</category>
    </item>
  </channel>
</rss>
