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!⚓︎
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⚓︎
Install Ditto⚓︎
Once logged in your updated VPS from your terminal:
1.b. Install system dependencies⚓︎
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]
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⚓︎
INSTALL...
Deno was installed successfully to ...
Run 'deno --help' to get started
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
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:
passwd: password updated successfully
Changing the user information for ditto
Enter the new value, or press ENTER for the default
Full Name []:
Room Number []:
Work Phone []:
Home Phone []:
Other []:
Is the information correct? [Y/n] Y
2. Install Ditto⚓︎
2.a. Download source code⚓︎
Cloning into '/opt/ditto'...
warning: redirecting to https://gitlab.com/soapbox-pub/ditto.git/
remote: Enumerating objects: 13338, done.
... done.
No message appears, which often means it worked.
No message should appear, which often means it worked.
2.b. Configure Ditto⚓︎
set up environment variables from /opt/ditto as user ditto
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]
? 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.
media uploads⚓︎
2.c. Add Soapbox⚓︎
from within /opt/ditto as user ditto
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)
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)
The password entered above should be the same as in step 2.b., higher up, when entering a Postgres password.
Update your database password⚓︎
ditto does not have sudo access, so the change will be made with postgres and later assigned to it
ALTER USER dittodbuser WITH PASSWORD 'your new database password';
2.e Start Ditto⚓︎
sudo cp /opt/ditto/installation/ditto.service /etc/systemd/system/ditto.service
no message appeared, likely successful.
no message appeared, likely successful.
Created symlink /etc/systemd/system/multi-user.target.wants/ditto.service → /etc/systemd/system/ditto.service.
check if ditto is running
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⚓︎
no message appears, likely successful.
config window⚓︎
open config file
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
Ctrl + O to save changesCtrl + X to exit
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.
Ctrl + O to save
Ctrl + X to exit
check syntax and possible errors
always restart after saving changes
check if ditto is running
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⚓︎
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):
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
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
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Would you be willing to share your email address ... support digital freedom.
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
(Y)es/(N)o: N
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):
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
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
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:
...
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
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
stop process with Ctrl + CA 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.