Skip to content

Setting up your own nostr community with Ditto⚓︎

The journey of setting up a nostr community without needing to develop a nostr app.

Now live!⚓︎

freedom weaver club

weird unmarketing cats joining efforts over coffee

Every learning journey takes some troubleshooting⚓︎

Jumping into new rabbit holes means learning new information and testing it, often needing to troubleshoot. This journey has been no different. Troubleshooting is often a blessing in disguise, needing to dig deeper into each layer of the installation.

These steps will likely work if using Linux or MacOS (Sorry, no Windows)

Special thanks to Shantaram, from project Ditto, who kindly helped me figure out the issues, answered my questions, and gave me extra information for the setup, which I'll be adding as I continue on this process. It is a much deeper rabbit hole than I could have imagined. If you have questions on how to run Ditto, you can reach him on nostr, or send him an email: me(at)shantaram.xyz

Resource: Ditto Installation Docs

What you need⚓︎


Terminal


VPS


Install Ditto⚓︎

Once logged in your updated VPS from your terminal:

1.b. Install system dependencies⚓︎

sudo apt install git curl unzip nginx postgresql-contrib certbot python3-certbot-nginx
message from terminal
Reading package lists... Done
Building dependency tree       
Reading state information... Done
The following packages were automatically installed and are no longer required:
  linux-image-5.4.0-26-generic linux-modules-5.4.0-26-generic
  linux-modules-extra-5.4.0-26-generic
Use 'sudo apt autoremove' to remove them.
The following additional packages will be installed:
...
Do you want to continue? [Y/n]
Y

You should see a progress bar at the bottom, as a long list of files gets installed.

If you get a pink window mentioning that services need to be restarted, hit enter. You will see a list of services to restart. Hit enter again. You should see a message that nothing else needs to be restarted, nor is anything outdated.

1.c. Install deno⚓︎

curl -fsSL https://deno.land/x/install/install.sh | sudo DENO_INSTALL=/usr/local sh -s v1.45.2
message from terminal
INSTALL...

Deno was installed successfully to ...
Run 'deno --help' to get started

sometimes asks:
Edit shell configs to add deno to the PATH? (Y/n)

DENO was added to the path

set up completions

1.d. Create the Ditto user⚓︎

Since the program, the user, and the database are all named ditto, it can get a little confusing, so I'm renaming the database names for a clearer example. You can use your own custom names, except for the server user (ditto).

server user: ditto

database user: dittodbuser

database: dittodb


create the ditto user

sudo adduser ditto

enter a password for ditto and retype it
Adding user 'ditto' ...
Adding new group 'ditto' (1001) ...
Adding new user 'ditto' (1001) with group 'ditto' ...
Creating home directory '/home/ditto' ...
Copying files from '/etc/skel' ...
New password: 
Retype password:
success message
passwd: password updated successfully
Changing the user information for ditto
Enter the new value, or press ENTER for the default
hit enter after each one
Full Name []:  
  Room Number []: 
  Work Phone []: 
  Home Phone []: 
  Other []:
Is the information correct? [Y/n] Y


2. Install Ditto⚓︎

2.a. Download source code⚓︎

sudo git clone https://gitlab.com/soapbox-pub/ditto /opt/ditto
message from terminal
Cloning into '/opt/ditto'...
warning: redirecting to https://gitlab.com/soapbox-pub/ditto.git/
remote: Enumerating objects: 13338, done.
... done.

assign ownership of folder to ditto
sudo chown -R ditto:ditto /opt/ditto

No message appears, which often means it worked.

deeper dive


navigate to the ditto directory
cd /opt/ditto
notice the change in location
yourusername@server1:/opt/ditto$

become ditto user
sudo su ditto
No message should appear, which often means it worked.

2.b. Configure Ditto⚓︎

set up environment variables from /opt/ditto as user ditto

create .env file
deno task setup
message from terminal
Task setup deno run -A scripts/setup.ts

Hello! Welcome to the Ditto setup tool. We will ask you a few questions to generate a .env file for you.

- Ditto docs: https://docs.soapbox.pub/ditto/
- Press Ctrl+D to exit at any time.

  Generated secret key

? What is the domain of your instance? (eg ditto.pub) [localhost:4036]
enter your website or subdomain
yourwebsite.somewhere
just hit enter, it will select postgres
Which database do you want to use?
> postgres
  sqlite
hit enter
? Postgres host localhost
hit enter or create a custom one
? Postgres port 5432
hit enter to keep ditto or type a custom database username then hit enter
? Postgres user dittodbuser

You will need to enter this same password when setting up the dittodbuser password (a few steps below).

For the time being, do not use special characters in the following password, but you can increase the length.

enter a database password
? Postgres password 
hit enter to keep ditto or add a custom database name
? Postgres database dittodb

media uploads⚓︎

hit enter
How do you want to upload files? 
> nostrbuild
  blossom
  s3
  ipfs
  local
hit enter
? nostr.build endpoint [suggested route]
message from terminal
Writing to .env file...
Done

2.c. Add Soapbox⚓︎

from within /opt/ditto as user ditto

deno task soapbox
a very very long list of files gets installed
Task soapbox curl -O https://dl.soapbox.pub/main/soapbox.zip && mkdir -p public && mv soapbox.zip public/ && cd public/ && unzip soapbox.zip && rm soapbox.zip
  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
100 20.8M  100 20.8M    0     0  9666k      0  0:00:02  0:00:02 --:--:-- 9662k
Archive:  soapbox.zip
  inflating: report.html             
   creating: packs/
  inflating: packs/audio.worker-PmTdibbe.js  
  ...
  ...
  ...             
  inflating: 404.html  

Type exit once to stop being the ditto user but remain in the same directory (/opt/ditto)

enter exit only once
exit

2.d. Provision the database⚓︎

This section differs from Ditto's installation docs, but it is how it worked for me.

create postgres user and database (from within /opt/ditto)

sudo -u postgres createuser -P dittodbuser
enter ditto user password
Enter password for new role:
Retype:

The password entered above should be the same as in step 2.b., higher up, when entering a Postgres password.

sudo -u postgres createdb dittodb -O dittodbuser

Update your database password⚓︎

ditto does not have sudo access, so the change will be made with postgres and later assigned to it

sudo -u postgres psql
that will log you in to your database
psql (version (Ubuntu)
Type "help" for help.

postgres=>
change password by adding it between the single quotation marks
ALTER USER dittodbuser WITH PASSWORD 'your new database password';
message from terminal
ALTER ROLE
close database
\q
assign ownership to ditto
sudo chown -R ditto:ditto /opt/ditto/.env
become ditto
sudo su ditto
deno task start
stop being ditto
exit

2.e Start Ditto⚓︎

from within the /opt/ditto folder
sudo cp /opt/ditto/installation/ditto.service /etc/systemd/system/ditto.service

no message appeared, likely successful.

reload
sudo systemctl daemon-reload

no message appeared, likely successful.

enable ditto to run automatically
sudo systemctl enable --now ditto
message from terminal
Created symlink /etc/systemd/system/multi-user.target.wants/ditto.service  /etc/systemd/system/ditto.service.

check if ditto is running

sudo systemctl status ditto

stop process with Ctrl + C

 ditto.service - Ditto
     Loaded: loaded (route:>
     Active: active (running) since - your ditto instance birthday
...
     CGroup:

if you visit your domain, you should see a message:

Welcome to nginx!

If you see this page, the nginx web server is successfully installed and working. Further configuration is required.

For online documentation and support please refer to nginx.org.
Commercial support is available at nginx.com.

Thank you for using nginx.

3. Getting online⚓︎

3.a. Configure Nginx⚓︎


correct location
sudo cp /opt/ditto/installation/ditto.conf /etc/nginx/sites-enabled/ditto.conf

no message appears, likely successful.


config window⚓︎

open config file

sudo nano /etc/nginx/sites-enabled/ditto.conf

server_name

You need to find the one example.com that appears under server_name, and add your domain, without the https://, just as in the example.com

original
server {
  server_name example.com;
Ctrl + O to save changes

Ctrl + X to exit

restart
sudo systemctl restart nginx

Original file for reference:

# Nginx configuration for Ditto.
#
# Edit this file to change occurences of "example.com" to your own domain.

upstream ditto {
  server 127.0.0.1:4036;
}

server {
  listen 80;
  listen [::]:80;
  location /.well-known/acme-challenge/ { allow all; }
  location / { return 301 https://$host$request_uri; }
}

server {
  server_name example.com;

  keepalive_timeout 70;
  sendfile on;
  client_max_body_size 100m;
  ignore_invalid_headers off;

  proxy_http_version 1.1;
  proxy_set_header Upgrade $http_upgrade;
  proxy_set_header Connection "upgrade";
  proxy_set_header Host $host;
  proxy_set_header X-Real-IP $remote_addr;
  proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
  proxy_set_header X-Forwarded-Proto $scheme;

  root /opt/ditto/public;

  location /packs {
    add_header Cache-Control "public, max-age=31536000, immutable";
    add_header Strict-Transport-Security "max-age=31536000" always;
    root /opt/ditto/public;
  }

  location ~ ^/(instance|sw\.js$|sw\.js\.map$) {
    root /opt/ditto/public;
    try_files $uri =404;
  }

  location /metrics {
    allow 127.0.0.1;
    deny all;
    proxy_pass http://ditto;
  }

location / {
    proxy_pass http://ditto;
  }
}

modifying nginx config⚓︎

Access the file again if you need to make any additional changes. If you get any errors, you need to review your file to correct them.

sudo nano /etc/nginx/sites-enabled/ditto.conf

Ctrl + O to save

Ctrl + X to exit

check syntax and possible errors

sudo nginx -t

always restart after saving changes

sudo systemctl restart nginx

check if ditto is running

sudo systemctl status ditto


3.b.i. Setting up nginx to serve local uploads⚓︎

There's an extra step here, which I haven't tried, if you didn't choose nostr.build for image uploads.



3.b. Obtain an SSL certificate⚓︎

sudo certbot --nginx
If your env file has no syntax errors, it will ask you for a contact email:

Saving debug log to /var/log/letsencrypt/letsencrypt.log
Plugins selected: Authenticator nginx, Installer nginx
Enter email address (used for urgent renewal and security notices) (Enter 'c' to
cancel):
agree to the terms of service
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Please read the Terms of Service at
https://letsencrypt.org/documents/LE-SA-v1.4-April-3-2024.pdf. You must agree in
order to register with the ACME server at
https://acme-v02.api.letsencrypt.org/directory
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
(A)gree/(C)ancel: A

share your email address
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Would you be willing to share your email address ... support digital freedom.
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
(Y)es/(N)o: N
it will display your domain name, enter 1
Which names would you like to activate HTTPS for?
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
1: your domain name
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Select the appropriate numbers separated by commas and/or spaces, or leave input
blank to select all options shown (Enter 'c' to cancel):
enter 2 to redirect all requests to HTTPS access
Please choose whether or not to redirect HTTP traffic to HTTPS, removing HTTP access.
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
1: No redirect - Make no further changes to the webserver configuration.
2: Redirect - Make all requests redirect to secure HTTPS access. Choose this for
new sites, or if you are confident your site works on HTTPS. 
You can undo this
change by editing your web server s configuration.
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Select the appropriate number [1-2] then [enter] (press 'c' to cancel): 2

success message with analyze link
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Congratulations! You have successfully enabled https://yourdomain

You should test your configuration at:
https://www.ssllabs.com/ssltest/analyze.html?d=yourdomain
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

IMPORTANT NOTES:
 - Congratulations! Your certificate and chain have been saved at:
   ...
visit the analyze link given by your terminal in the previous step
A grade 
for 
certificate
protocol support 
key exchange 
cipher strength

HTTP request failed
Server supports TLS 1.3
Trusted Yes

It expires in over 2 years

Qualys SSL labs documentation page

restart nginx

sudo systemctl restart nginx
after getting ssl the config file changes with added details
    listen 443 ssl; # managed by Certbot
    ssl_certificate /route; # managed by Certbot
    ssl_certificate_key /route; # managed by Certbot
    include /etc/letsencrypt/options-ssl-nginx.conf; # managed by Certbot
    ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem; # managed by Certbot

}


server {
    if ($host = yourdomain.ending) {
        return 301 https://$host$request_uri;
    } # managed by Certbot


  server_name yourdomain.ending;
    listen 80;
    return 404; # managed by Certbot


}

check again if ditto is running

check status
sudo systemctl status ditto
stop process with Ctrl + C


A community is born⚓︎

At this step, you should be able to see the Ditto template, if you visit your website. 🤙

The next step is to customize it to your niche audience.