this post was submitted on 27 Aug 2025
127 points (99.2% liked)

Selfhosted

50876 readers
439 users here now

A place to share alternatives to popular online services that can be self-hosted without giving up privacy or locking you into a service you don't control.

Rules:

  1. Be civil: we're here to support and learn from one another. Insults won't be tolerated. Flame wars are frowned upon.

  2. No spam posting.

  3. Posts have to be centered around self-hosting. There are other communities for discussing hardware or home computing. If it's not obvious why your post topic revolves around selfhosting, please include details to make it clear.

  4. Don't duplicate the full text of your blog or github here. Just post the link for folks to click.

  5. Submission headline should match the article title (don’t cherry-pick information from the title to fit your agenda).

  6. No trolling.

Resources:

Any issues on the community? Report it using the report flag.

Questions? DM the mods!

founded 2 years ago
MODERATORS
 

Today, we're excited to announce the release of Linkwarden 2.12! đŸ„ł This update brings significant improvements and new features to enhance your experience.

For those who are new to Linkwarden, it’s basically a tool for saving and organizing webpages, articles, and documents all in one place. It’s great for bookmarking stuff to read later, and you can also share your resources, create public collections, and collaborate with your team. Linkwarden is available as a Cloud subscription or you can self-host it on your own server.

This release brings a range of updates to make your bookmarking and archiving experience even smoother. Let’s take a look:

What’s new:

đŸ«§ Drag and Drop Support

One of our most requested features is finally here! You can now drag and drop Links onto Collections and Tags. This makes it much easier to organize your bookmarks and keep everything tidy.

đŸ“€ Upload from SingleFile

SingleFile is an awesome browser extension that allows you to save complete webpages as a single HTML file on your device. As of Linkwarden 2.12, you can upload your saved links directly from the SingleFile browser extension into Linkwarden. This allows you to easily save articles which are behind paywalls or require authentication directly from your browser.

To use this feature, simply install the SingleFile extension, and then follow the documentation.

🌐 Progressed Translations

We’ve made significant progress in our translations, with many languages now fully supported. If you’re interested in helping out with translations, check out our Crowdin page.

✅ And more...

There are also a bunch of smaller improvements and fixes in this release to keep everything running smoothly.

Full Changelog: https://github.com/linkwarden/linkwarden/compare/v2.11.8...v2.12.0

Want to skip the technical setup?

If you’d rather skip server setup and maintenance, our Cloud Plan takes care of everything for you. It’s a great way to access all of Linkwarden’s features—plus future updates—without the technical overhead.


We hope you enjoy these new enhancements, and as always, we'd like to express our sincere thanks to all of our supporters and contributors. Your feedback and contributions have been invaluable in shaping Linkwarden into what it is today. 🚀

you are viewing a single comment's thread
view the rest of the comments
[–] daniel31x13@lemmy.world 3 points 11 hours ago (1 children)

So you want to disable registration? It's possible.

[–] glizzyguzzler@piefed.blahaj.zone 6 points 10 hours ago (2 children)

No what I said isn't about user registration; it's about adding these to the docker-compose.yml:

        read_only: true
        user: 6969:6969

to prevent running as root and making the file system read-only. The API needs to be exposed without a VPN or other proxy login since my parents' can't handle that, so if I was able to implement these recommended security steps I'd feel like I could open up the container to the internet at large without too much risk.

Per this issue https://github.com/linkwarden/linkwarden/issues/799 it seems like there's a lot of steps to take to get these settings to work.

It would be also ideal if I didn't have to give the container (but not a deal-breaker):

        cap_add:
          - CAP_SYS_ADMIN
          - CAP_SYS_CHROOT

as the issue also states is required for the headless chrome scraper browser.

I am using it internally now and it's really good, but to open it up for my parents (which I think they'd dig) I'd definitely want these security settings on without major issues. Linkwarden is an internet-facing application so these recommended security practicies are in its wheel-house, feature-wise, as well.

Hope that helps clear up my comment!

[–] daniel31x13@lemmy.world 4 points 9 hours ago (1 children)

Oh I see, thanks for letting me know! Yes that's actually requested and we'll be getting to it sometime.

Great to hear! It’s seriously slick and “just works”. With those security features up you can tout them on the cloud offering too :)

[–] somethingsomethingidk@lemmy.world 1 points 9 hours ago* (last edited 4 hours ago) (1 children)

So I have mine running in a podman quadlet. It runs as root in the container but it is unpriviledged. Mine has NET_ADMIN and SYS_MODULE but I honestly can't remember why... SYS_ADMIN seems extreme though

Edit: I'm dumb, and the linkwarden container has no capabilities set. I set them for the tailscale container which definitely needs it.

[–] glizzyguzzler@piefed.blahaj.zone 1 points 8 hours ago* (last edited 8 hours ago) (1 children)

Care to share your quartet? I’m just getting into the quads with trixie out - and I haven’t gotten this working yet


The permissions do seem intense; if you’re getting by without maybe those aren’t quite needed!

[–] somethingsomethingidk@lemmy.world 1 points 5 hours ago* (last edited 4 hours ago) (1 children)

Sure thing, I'll edit this reply when I get back to my computer. Just note that I also have a tailscale and nginx container in the pod which are not necessary.

You'll see my nginx config which reverse proxies to the port the service is running on. On public servers I have another nginx running with SSL that proxies to the port I map the pod's port 80 to.

I usually run my pods as an unpriviledged user with loginctl enable-linger which starts the enabled systemctl --user services on boot.

All that being said I haven't publically exposed linkwarden yet, mainly because it's the second most resource intensive service I run and I have all my public stuff on a shitty vps.

Edit: My opsec is so bad hahaha

Edit2: I just realized the caps I gave were to the tailscale container, not the linkwarden container. Linkwarden can run with no caps :)

I added the tailscale stuff back

files:

linkwarden-pod.kube:

[Install]
WantedBy=default.target

[Kube]
# Point to the yaml in the same directory
Yaml=linkwarden-pod.yml
PublishPort=127.0.0.1:7777:80
AutoUpdate=registry

[Service]
Restart=always

linkwarden-pod.yml:

***
apiVersion: v1
kind: Pod
metadata:
  name: linkwarden
spec:
  containers:
    - name: ts-linkwarden
      image: docker.io/tailscale/tailscale:latest
      env:
        - name: TS_HOSTNAME
          value: "link"
        - name: TS_STATE_DIR
          value: /var/lib/tailscale
        - name: TS_AUTHKEY
          valueFrom:
            secretKeyRef:
              name: ts-auth-kube
              key: ts-auth
      volumeMounts:
        - name: linkwarden-ts-storage
          mountPath: /var/lib/tailscale
      securityContext:
        capabilities:
          add:
            - NET_ADMIN
            - SYS_MODULE

    - name: linkwarden
      image: ghcr.io/linkwarden/linkwarden:latest
      env:
        - name: INSTANCE_NAME
          value: link.mydomain.com
        - name: AUTH_URL
          value: http://linkwarden:3000/api/v1/auth
        - name: NEXTAUTH_SECRET
          value: LOL_I_JUST_PUBLISHED_THIS_I_CHANGED_IT
        - name: DATABASE_URL
          value: postgresql://postgres:password@linkwarden-postgres:5432/postgres
        - name: NEXT_PUBLIC_DISABLE_REGISTRATION
          value: "true"

    - name: linkwarden-nginx
      image: docker.io/library/nginx:alpine
      volumeMounts:
        - name: linkwarden-nginx-conf
          subPath: nginx.conf
          mountPath: /etc/nginx/nginx.conf
          readOnly: true

    - name: linkwarden-postgres
      image: docker.io/library/postgres:latest
      env:
        - name: POSTGRES_PASSWORD
          value: "password"
      volumeMounts:
        - name: linkwarden-postgres-db
          mountPath: /var/lib/postgresql/data

  volumes:
    - name: linkwarden-nginx-conf
      configMap:
        name: linkwarden-nginx-conf
        items:
          - key: nginx.conf
            path: nginx.conf
    - name: linkwarden-postgres-db
      persistentVolumeClaim:
        claimName: linkwarden-postgres-db-claim
    - name: linkwarden-ts-storage
      persistentVolumeClaim:
        claimName: linkwarden-ts-pv-claim

***
apiVersion: v1
kind: ConfigMap
metadata:
  name: linkwarden-nginx-conf
data:
  nginx.conf: |
    #user  nobody;
    worker_processes  1;
     #pid        logs/nginx.pid;


    events {
        worker_connections  1024;
    }


    http {
        include       mime.types;
        default_type  application/octet-stream;


        sendfile        on;

        #keepalive_timeout  0;
        keepalive_timeout  65;

        gzip  off;

        # set_real_ip_from cw.55.55.1;
        real_ip_header X-Forwarded-For;
        real_ip_recursive on;

        server {
            listen       80;
            server_name  _;

            location / {
                    proxy_pass http://localhost:3000/;

                    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
                    proxy_set_header X-Forwarded-Port $server_port;
                    proxy_set_header X-Forwarded-Scheme $scheme;
                    proxy_set_header X-Forwarded-Proto  $scheme;
                    proxy_set_header X-Real-IP $remote_addr;
                    proxy_set_header Accept-Encoding "";
                    proxy_set_header Host $host;
            }
        }
    }

I also have a little helper script you might like

copy.sh:

#!/bin/bash

SYSTEMD_DIRECTORY="${HOME}/.config/containers/systemd"
POD_NAME="linkwarden-pod"

mkdir -p "$SYSTEMD_DIRECTORY"
cp "${POD_NAME}".{kube,yml} "${SYSTEMD_DIRECTORY}"/

systemctl --user daemon-reload

Thanks! This’ll def help me get tooled up for podman :)