Repository navigation
Linger 0.5.0: reactions, polls, talking from inside a game, and a sturdier server
The biggest release so far. Reactions are back, the way Discord and Slack do
them. The host can ask a room a question with /poll. Push-to-talk works
with a game in front. You can leave a group DM. The crackle at the start of
every sentence in voice is fixed for real this time. And before the release,
the app and the server went through an audit for safety and speed: about
forty fixes came out of it, from a tiny picture that could stop a server to a
minimized window that kept drawing for nobody.
Everyone: update the app. The voice fix is in the app that's listening,
and most new things need the new app.
Hosts: update the server, and read For hosts
first. This update has more steps than usual. It changes the database,
so going back to 0.4.10 means restoring the copy update.sh makes. If you
run the voice relay, you need the new compose.yaml and more ports open, in
that order. Most of the new things need the server as well as the app.
The highlights
- Reactions are back (#485). A small pill under a message with the emoji
and how many people left it. Any emoji, six different ones on a message at
most, and they never notify anybody. - Polls (#474). The host or a co-host types
/pollin a room, and
everybody votes with a click. - Push-to-talk works with a game in front (#500), on Windows and Linux,
and with Linger minimized or in the tray. - No more crackle at the start of a sentence (#470). 0.4.10's fix was
aimed at the wrong cause. This one found the real one. - Leave a group DM (#565), and nobody can put you back.
- A forgotten password has a way back (#581): the host makes a sign-in
link in the app. No more stopping the server. - The server backs itself up every night (#582), and tells the host when
its disk is filling up. - Old files stay until the server needs the room (#583), instead of going
after a year.
Reactions
- Pills under a message (#485): other people's are grey, yours are blue
with an outline. Click one to add yours, and click yours to take it back.
Point at a pill to see who left it. On a phone, hold it (#573). - Any emoji, the server's own included. On a computer, point at a message
and click the smiley beside its ⋯, or the smiley-plus after its reactions.
On a phone, hold the message: it shows the six emoji you use most and a
button for every emoji. - Six different reactions on a message at most.
- Never a notification, a sound or a lit row.
- The host can turn them off for a room (Settings → Hosting → Rooms →
Edit → Reactions). They're hidden, not deleted. You can hide them for
yourself in Settings → Appearance → Show reactions. DMs always have them. - Removing one of the server's own emoji removes the reactions made with it.
- Friends on 0.4.10 or older don't see reactions until they update. On a
server that hasn't updated, the app shows no reaction buttons.
Polls
- Asking (#474). The host or a co-host types
/pollin a room's message
box, with the question after it if they like, and presses Enter. A panel
opens: two to ten choices, whether people can pick more than one, and when
it closes (a day to four weeks; a week to start with). Nothing is posted
until Post poll. Rooms only, not DMs. - Voting. Everybody votes with a click, the person who asked included.
Click another choice to move your vote, or yours to take it back, until it
closes. You see the results before you vote, and votes aren't secret: each
choice shows who picked it as dots in their colors. - Closing. It closes when its time is up, or when whoever asked presses
Close poll. A quiet grey line at the bottom of the room then says what
won, with See results. - It pokes nobody. A new poll makes the room look new, like anything
said. No notification and no sound. - Every
/command is the host's or a co-host's now. Anybody else's box
says who can, and nothing is sent. - Friends on an older app see the question and its choices as a list.
In the room
- "Jules joined voice" (#473). When somebody joins a room's voice and
stays ten seconds, the room gets one quiet grey line, so people reading can
see the talk moved to voice. Joins close together share one line. It's
written at most once per person per room every ten minutes, and it never
notifies. There's no line for leaving. - Fewer chimes (#473). Each person's join and leave chime plays at most
once a minute, so somebody dropping in and out doesn't ring the room each
time. Setting a message of the day no longer chimes either. - A time written with a zone reads in your own clock (#584). "8PM CDT"
gets a faint dotted underline. Point at it, or tap it on a phone, and it
says "9:00 PM for you". It works in messages, the message of the day and
polls, old messages included. Short names that mean more than one place
(CST, IST, BST) are left alone rather than guessed. - Your local time on your card, if you turn it on (#604): Settings →
Profile → Show my local time. Friends see "3:12 AM for Jules" on your card
and on your Knock button, so they know it's late before they knock. It
starts off, and it follows the computer or phone you last opened Linger on.
On a server that hasn't updated, the switch stays off and says "This server
needs updating before it can show your time." (#640)
Group DMs
- Leave a group DM (#565): the ⋯ on its row or in its header, then
Leave this group…. It goes from your list on every device you're signed
in on. The others get a quiet line, "Callie left". Asking for a DM with the
same people again makes a new one, so nobody is pulled back in. - The last person out deletes it, messages and files, since nobody could
ever read it again. The question says so first. Export before you leave if
you want a copy. - A one-to-one DM can't be left: it's that friend's row.
- Friends on an older app see "left" as an ordinary message from that person.
Push-to-talk with a game in front
- The talk key works while another app is in front (#500), and with
Linger minimized or in the tray, the way Discord does. Linger listens for
that one key, and only while you're in voice with push to talk on. It sees
no other key and sends nothing about your keys anywhere. The game still
gets the key too. - Windows: it just works, and the key can be a mouse's middle or side
button (Mouse 4, Mouse 5). A game run as administrator hides its keys from
Linger, as it does from Discord. - Linux: your desktop hands Linger the key. KDE and GNOME ask which key
the first time you join voice with push to talk on. On Hyprland (Omarchy
included), Settings → Sound & Voice shows one line to add to your config.
It needs Linger installed (the Arch package,.deb,.rpmor AppImage).
The user guide has the details. - A Mac built from source asks macOS about the key the same way (#587). It
hasn't been tried on a real Mac yet. - The tray icon shows you're in voice (#601). The door gets an amber
microphone while your microphone is on, and a grey crossed-out one while
you're muted or deafened. On Windows, pointing at it says where you are.
A forgotten password
- The host makes a sign-in link (#581) in Settings → Hosting → People →
Sign-in Links: pick the person, press Make a sign-in link, and send it
the way you'd send an invite. It works once, for 24 hours. Only the host
can make one, not a co-host, and nobody can make one for the host. - The friend pastes it into Server or link, chooses a new password, and
is in. Every other place they were signed in is signed out. - Nobody is surprised. Their Settings → Account & App says a link was
made for them, and when it was used. The sign-in screen now says "Forgot
your password? Ask the host for a sign-in link".
Invite links in a browser
- A page instead of an error (#578). A friend who opens an invite link
before they have Linger used to get an empty error page. Now they see
"You're invited to …", how long the invite has left, where to get Linger,
and a Copy button. A used-up or expired invite says so. A setup link
gets the same page, with a red "Don't share this link". - Open in Linger (#607). A friend who already has Linger gets a button
on that page that opens the app with the invite in its box. They check the
address and press Continue: nothing is contacted until they do. With an
older app the button does nothing, so copy and paste the link as before.
Media and exports
- Leaving soon (#583), a new filter in Media, shows which files would be
cleared next, so you can star what you want to keep. While the server has
plenty of room it shows nothing. - Exports open in any web browser (#585). Unzip and double-click Open
me.html: every room and DM, laid out like Linger, with pictures, videos,
sound, reactions and polls. It works offline, years from now. Each
conversation is also there as a.jsonfile, for programs. - An export's link lasts a week (#504), and the app says the date it
stops working.
Voice
- No crackle at the start of a sentence (#470). Everybody's first words
had a little crackle, on any connection, a wired one included. 0.4.10
blamed packets arriving late, and that was wrong. The real cause was the
app's own queue of sound waiting to play: it slipped tiny bits of silence
into the rising first syllable of nearly every sentence. Now it only adds
silence where there already is some. The fix is in the app that's
listening, so you hear clean voices once your own app is 0.5.0. - The microphone turns off when you're dropped from voice (#589). After
the computer slept for more than two minutes, the server restarted, or you
signed out, Linger showed you out of voice but kept the microphone open, so
the system's mic light stayed on. It lets go now. Press Join to carry on.
Signing out of a server while in voice there also leaves voice at once,
rather than two minutes later. - A double-click on Join (#510) put you in voice deafened, because the
second click landed on Deafen. A double-click now counts as one click, and a
double-click on Leave no longer joins you straight back.
Safety
The audit looked for ways somebody could fool you or get at your things.
What it found, all fixed:
- A link can't hide another link (#508). A link written inside another
link's words opened both pages at once, and the hidden one ended up in
front. Now it's one link, to where it really goes. - A link whose words name another site shows where it really goes (#580):
www.paypal.com (evil.example), with the real site in grey beside it. A
name spelled with look-alike letters from another alphabet shows its true
form (xn--…). It works on old messages too, and in exports. - A file's name can't pretend to be something else (#488). Invisible
characters that turn text around could make a program look like a PDF: a
file namedinvoice, then one of those characters, thenfdp.exe, showed
as "invoiceexe.pdf". The server takes those characters out of file names,
statuses, room names and topics, polls and the message of the day. Hebrew
and Arabic still look as written. - Nobody can take a name that looks like someone else's (#574):
matt
besideMatt, a Cyrillic letter in place of a Latin one,rnform. The
name field says so. Names already in use aren't changed. - Changing your password signs you out everywhere else, at once (#496),
a computer you forgot about included. The device you change it on stays
signed in. Update the app before you change your password: on an
updated server, an app from 0.4.10 or earlier can sign itself out right
after the change, and you'd sign in again with the new password. - A deleted message's files go at once (#502). Before, a file's link kept
working for up to six hours after its message was deleted. - Linux banners show a message's words as typed (#489). A message with
<b>in it showed bold in the desktop banner, and on KDE could put a link
there.
Safety on the server
These protect a host's server from a member, or a stranger, trying to break
it. They come with the server update.
- One tiny picture could stop a server (#487). A 35-byte GIF claiming to
be enormous made it run out of memory. Every picture now has a memory
budget, and at most two are worked on at once. Very large progressive JPEGs
and WebPs, and very long GIFs, now get "That image can't be read." When two
big pictures are already being worked on, the next waits up to ten seconds,
then says "The server is busy with other pictures. Send this one again in a
moment." - Strangers can't make a server work hard on demand (#495, #546). Joining
checks the invite before the password. At most four passwords are checked at
once. Sign-ups from one network are limited, 60 an hour to start with. The
limits can't be dodged with a made-up header or by hopping between IPv6
addresses. Whoever meets a limit is told why, and how long to wait. - The voice relay carries voice to its own server and nowhere else
(#501). Before, a member could use it to reach other things on the host's
network. - The server's data is its own (#506). On a machine with more than one
account, the others can't read the database, the files, the backups or
.env. - One member can't fill the server's storage (#503). Each person can have
1 GB going up at once. Space held by an upload that went quiet comes back
after an hour, files uploaded but never sent go after a week, and removing
somebody frees their space. Taking a file out of the message box while it's
going up now stops it. - Smaller fixes: an upload to an S3 bucket can't be bigger than it said it
was (#505); link previews can't reach private addresses dressed up as IPv6
ones (#490); a connection that hasn't signed in can't send huge messages
(#517); an away message has the same length limit everywhere (#497); one
app can't flood a server with room moves, away changes or voice joins
(#497, #527); export archives no longer pile up on the disk (#504); used
sign-in tokens are deleted after 30 days (#520); a search with an invisible
NUL character in it no longer fails (#498). - Behind the scenes: every tool the release build borrows is pinned to
exact code, so nobody could swap one to sign a bad update (#491). The list
window can't show a banner of its own around the app's rules (#548).
Speed and memory
In the app:
- A smaller app (#521). The Linux program is 25 MB instead of 43 MB,
and the phone's.apkis about a third smaller (13 MB instead of 20 MB). - How fast it opens is measured now: about a second (#591). Dates are
made ready when one is shown, not every time a window opens (#535). - Less work while nothing happens. An open conversation no longer redraws
its window every two seconds (#511). A window's sound shuts between sounds,
instead of playing silence all day (#531). The Shimmer name costs about half
as much (#532). On Windows, a minimized Linger, or one in the tray, stops
drawing (#594). - Less work when something does happen (#533). Something on one server
redraws that part of the list, not the whole list: a friend going away on
another server draws 26 pieces instead of 202. Thirty servers can sign in
at once without some of them failing to show. - No slow leak (#534). Switching conversations kept a little memory every
time, about 6 MB per thousand switches. It lets go now. - The list asks each server for its name and color when it connects and then
hourly, not every two minutes (#536). A host's own change still shows at
once.
On the server:
- Faster as it grows (#518). On a server with a year of messages,
opening Media went from about 450 ms to 25 ms, and a search from about
140 ms to 1 ms. - An idle server rests (#522). With nobody in voice, voice forwarding
still woke 50 times a second. Now it waits for somebody to join. - Memory comes back after sign-ins (#523). Each password check borrows
about 19 MB, and the server never gave it back. After 280 sign-ups it held
1.9 GB; now it holds 21 MB. - Less memory for each person connected (#519). Each event is turned into
text once and shared, rather than once per person. - Smaller cleanups from the same audit (#524).
Fixes
- A room that came up empty after the computer woke (#468) now loads by
itself, trying again for half a minute, and opening it again tries again. - The AppImage opened an empty window on newer graphics drivers (Mesa
26.2, Omarchy with an AMD card, say) (#479). If yours did, download this
release's AppImage by hand. - Linux: Linger could quit when a conversation opened beside the list
(#628). Fixed. - Windows: an update could stop on "Error opening file for writing"
(#568), when Windows happened to be reading the program right then. It now
waits up to ten seconds and carries on. - One part that can't be drawn no longer blanks the whole window (#509).
Its place says "This conversation couldn't be shown." with Try again,
and everything else keeps working. - A new message is followed down (#625) when you were resting just short
of the bottom, or a link card above was loading at that moment. It's marked
read too. - Retry never posts a message twice (#524). When the answer to a send got
lost after the server had saved it, Retry posted a copy, and a photo's Retry
was refused. Polls the same. This needs the server update. - Phone photos show the right way up (#569). The server threw away the
photo's "this way up" note along with its location. Photos already sent
sideways stay sideways. - Pictures, pastes, knocks and dates (#512). A very tall picture, like a
phone's scrolling screenshot, stays wide enough to see. A picture that can't
load says so, with Load again. A paste over 8,000 characters says only
the start fit. A second knock from one person replaces their first, and at
most three knocks show at once. A message dated in the future, from a server
whose clock runs ahead, shows its date. A message made only of invisible
letters is refused, like an empty one. - At big interface sizes (150%, say), windows can't be dragged too small
to type in (#512). A long name in wide letters no longer squeezes out "in
#room", and emoji in a gradient name keep their own colors. - An export no longer fails for somebody with DMs with two people the host
has since removed (#585). - Only words worth copying can be selected (#483): the conversation,
people's cards, the message of the day, what you type, and errors. The list,
labels and buttons can't, as in any desktop app. The message box's hint
can't either (#478).
Under the hood
- Releases are built with tauri-action 1.0, and
latest.jsonstill points at
the normal download links (#597). A practice tag publishes no server image. - Every workflow action is pinned to a commit, and Dependabot proposes newer
ones once a month (#491). - Tests that failed at random on a busy machine were each fixed for their own
cause (#461, #525, #528, #559, #567, #572, #637). scripts/tidy-branches.shdeletes finished branches (#472), and a new issue
that arrives without a label gets one from its words (#481).- How fast Linger opens is measured in
docs/performance.md(#591). Ambient
voice (M13) is cut (#600). - The guides cover reactions (#537), and the VPS guide's firewall table opens
UDP 3479 (#564).
Known issues
- "App not installed" on Android when installing over a Linger that was
signed differently, like a test build from a computer. Uninstall it once,
which signs you out, then install this one. Releases install over each other. - Read positions don't move live between two devices that are both open.
Read a room on the phone while the computer is open, and the computer shows
it as new until it next connects afresh (a restart, say). Your own messages
are fine either way. - The phone app doesn't update itself. Install each new
.apkover the
old one. - On Hyprland (Omarchy included), the mouse pointer jumps into a
conversation that opens in a window of its own. The
user guide has the two lines that turn it
off. - The AppImage doesn't play AV1 videos (#358). Windows and the Arch,
.deband.rpmpackages do.
For hosts: updating the server
Server image: ghcr.io/itsmattguenther/linger:0.5.0 (x86-64 only), also
tagged 0.5 and latest.
What changes for you
- The database changes. Ten changes (0013 to 0024; 0021 and 0022 aren't
used) run by themselves the first time 0.5.0 starts. That first start can
take a second or two longer than usual, once.update.shsaves the
database just before, and that copy is how you'd go back: 0.4.10 won't
start on a database 0.5.0 has changed. - A new
compose.yaml, which relay hosts need. It keeps the relay to
voice for your own server (#501), and gives it 200 ports instead of 41, so
a raid fits (#197). Those ports have to be open first (step 3). - Files stay longer. The new default is
LINGER_FILE_EXPIRY_DAYS=when-full: nothing is deleted for being old. Once
uploads fill 90% ofLINGER_POOL_BYTES, the oldest unstarred files go until
it's back under 80% (#583). Before, a file went a year after it was shared.
For the old rule, putLINGER_FILE_EXPIRY_DAYS=365in.env. If you had set
a number already, nothing changes. On S3, the bucket now fills up to
LINGER_POOL_BYTESbefore anything goes, and you pay for what's in it. - A copy of the database every night, into
data/backups/(#582). It
keeps a week of nightly copies and a month of weekly ones. Each is about the
size of your database (not the uploaded files), so it takes some disk. To
stop it, if you already back updataanother way, put
LINGER_BACKUPS=offin.env. The copies are on the same disk as the
server, so Backups in the host guide says how to
keep one somewhere else too. - Lines for you at the foot of your list, seen by the host only: when the
disk is nearly full, when files have used up their space and nothing is left
that could go, or when the server hasn't backed up for three days.
Settings → Hosting → Server says when the last copy was made. - New settings, all optional, all in the new
.env.example. Leave them
out and nothing changes:LINGER_BACKUP_S3_*sends each night's copy to a bucket too, so it
survives the machine (#614). The host guide's
Sending the copies to a bucket
says how.LINGER_SIGNUPS_PER_HOUR(60 to start with) is how many people may sign
up from one network in an hour. Raise it, or set it tooff, before a big
group joins together from one place (#495).
A big group joining at once
has the details.LINGER_PASSWORD_CHECKS_AT_ONCE(4 to start with) is how many passwords
the server checks at the same time. Each takes about 19 MB of memory and a
processor core for a moment.LINGER_TRUSTED_PROXIES(privateto start with) is only for a proxy
that isn't on this machine or a private network, like Caddy on a VPS
reaching a home server over Tailscale:private,100.64.0.0/10. Behind
such a proxy and without it, everybody shares one allowance for signing
in, so one stranger could lock everyone out. The usual setup, Caddy next
to Linger, needs nothing.
- Sign-in links replace
reset-passwordfor a member who forgot their
password: Settings → Hosting → People → Sign-in Links.reset-passwordon
the machine stays your own way back into your own account. - What needs the server updated, not just the app: reactions, polls, the
"joined voice" line, leaving a group DM, sign-in links, local time on your
card, the invite page and Open in Linger, Leaving soon, the backup and disk
lines, Retry never posting twice, and the week-long export link. Friends
on older apps keep working with the new server; the new things show up for
them as they update. - Changing a password on an older app. On this server, an app from 0.4.10
or earlier can sign itself out right after its person changes their
password. Signing in again with the new password fixes it. Nobody is signed
out by the update itself. - Only the server can open the
datafolder now (#506). From an account
other than root,ls datais refused.update.shdoesn't need to look
inside: it copies the database out through a container, with nosudo.
Its copies inbackups/are readable by you alone. - A deleted message's files go at once (#502), and files are now served
as private to caches. Behind a caching proxy like Cloudflare's, files come
from your server rather than the proxy, which uses a little more of your
bandwidth. - On S3, add a cleanup rule that deletes anything under
uploads/after
two days (#505). The host guide's
Settings you might want to change
says where that is on R2 and AWS. - Exports go a week after they're made, and straight away with a member
you remove. A server short of disk refuses to build one rather than filling
up (#504). - A new server set up with
setup.shtakes its files from the newest
release, so they match the server Docker downloads, rather than from
main(#507).
The steps
Run these on the server, one block at a time, in this order. Each step
says why it's there. If you type sudo before docker commands, do the same
for every docker command and for ./update.sh below.
1. Go to your linger folder and keep copies of your files. If anything
goes wrong, these are how you put things back as they were.
cd ~/linger
cp compose.yaml compose.yaml.before-0.5.0
cp Caddyfile Caddyfile.before-0.5.0
cp .env .env.before-0.5.0
chmod 600 .env.before-0.5.0(If your folder is somewhere else, cd to the one with your compose.yaml.)
chmod 600 keeps the copy of .env readable by you alone, since it holds the
relay's secret. If cp .env says there's no such file, that's fine: an older
server without the relay may not have one.
2. Find out where your settings are.
grep '^LINGER_DOMAIN=' .env- It prints your server's name, like
LINGER_DOMAIN=linger.example.com.
Your settings are in.env: you set up withsetup.sh, or by hand from
0.4.9. The new files can simply replace the old ones. Go on to step 3. - It prints nothing, or "No such file". Your settings are written inside
compose.yaml, from a server set up before 0.4.9. The newcompose.yaml
reads every setting from.env, so putting it in place of yours as it is
would lose your server's name and settings. You'll move them into.envin
step 4, before anything replaces the old file.- No relay? Then you don't need the new files at all: your old
compose.yamlkeeps working with 0.5.0. Skip to step 5.
- No relay? Then you don't need the new files at all: your old
3. Run the voice relay? Open its new ports first. To see whether you run
it:
docker ps -a --format '{{.Names}}'(Put sudo in front if you type it before docker commands.) If no name has
coturn in it, you don't run the relay: skip to step 4.
If you do, the new compose.yaml gives the relay UDP ports 49160 to
49359, where it had 49160 to 49200. Open them before you get the new
file. With the new compose.yaml and the old firewall, the relay hands most
of the people who need it a port your firewall drops, and they can't get into
voice. Everybody whose voice goes straight to your server is fine either way.
-
DigitalOcean: in the control panel, open Networking → Firewalls. If
your droplet is in one of the firewalls listed (many droplets have none, and
then there's nothing to do here), open it, and under Inbound Rules add a
Custom rule: protocol UDP, port range49160-49359, sources All
IPv4 and All IPv6. Save it. The old49160-49200rule can stay or go. -
Another provider (Hetzner, Linode, AWS and the rest): the same in its
firewall or security group. Allow inbound UDP 49160 to 49359. -
At home: on your router, forward UDP 49160 to 49359 to the server, in
the same place you forwarded 49160 to 49200 before. -
On the server itself, whatever the provider:
sudo ufw status
Only if it says
Status: active, run:sudo ufw allow 49160:49359/udp
If it says
inactive, there's nothing to do.
Last, check .env starts the relay with everything else:
grep '^COMPOSE_PROFILES=voice' .envIf that prints nothing, add the line once: echo COMPOSE_PROFILES=voice >> .env.
4. Get the new files. If step 2 found your settings inside
compose.yaml, follow
Moving an older server's settings into .env
in the host guide first. Where it says to download the files, use the
commands just below: they fetch 0.5.0's. Its first step, keeping copies of
the old files, you did in step 1. Then go on to step 5.
Everybody else:
curl -fLO "https://raw.githubusercontent.com/itsMattGuenther/Linger/v0.5.0/deploy/compose.yaml"
curl -fLO "https://raw.githubusercontent.com/itsMattGuenther/Linger/v0.5.0/deploy/Caddyfile"
curl -fLO "https://raw.githubusercontent.com/itsMattGuenther/Linger/v0.5.0/deploy/update.sh"
curl -fLO "https://raw.githubusercontent.com/itsMattGuenther/Linger/v0.5.0/deploy/.env.example"
chmod +x update.shThey come from the 0.5.0 release, so they go with the server you're about to
get. Your .env isn't touched: .env.example only lists the new settings, as
comments. If you run the relay, this compose.yaml is also what keeps the
relay to voice (#501), so you need it even apart from the ports.
Did you pin a version? If you had changed the image: line to stay on a
version, the new file says latest again. Look at the old one:
grep 'image: ghcr' compose.yaml.before-0.5.0If it ends in a version, like :0.4.10, open the new file with
nano compose.yaml and give its image: line a version the same way (:0.5.0
to take this one). Save with Ctrl+O, Enter, then Ctrl+X. Anything
else you had changed in the old compose.yaml by hand, a wider relay range
say, change in the new one too.
5. Update.
./update.sh(Use sudo ./update.sh if you type sudo before docker commands.) It says
where voice goes, downloads 0.5.0 while the server keeps running, stops it for
a few seconds to save the database into backups/, then starts everything
again, the relay too, and prints the version before and after. The database
changes run then, by themselves. If 0.5.0 doesn't start, update.sh prints the
commands that put 0.4.10 back.
6. Check it worked.
docker compose pslinger and caddy, and coturn if you run the relay, say Up. Wait about
30 seconds and run it again: still Up, not Restarting.
curl -f https://linger.example.com/api/v1/healthWith your own address in place of linger.example.com, it prints
{"ok":true,"version":"0.5.0"}.
docker compose logs linger | grep 'voice forwarding'It prints a line saying voice forwarding is on, with the address voice goes
to. (Nothing, if you set LINGER_VOICE_ADDRESS=off.)
If you run the relay:
docker compose --profile voice logs coturn | head -n 5
docker compose --profile voice logs --tail 20 coturnOne of the first lines says the relay carries voice to your server's public
address and nowhere else. The last lines shouldn't say it's stopping, or that
the secret is empty. If it says the relay carries nothing, or that DNS gave no
answer, The voice relay in the host guide
says what to do.
Then join voice from the app, with a friend on another network if you can,
and check you hear each other.
7. If something's wrong later: going back to 0.4.10. update.sh saved
the database into backups/ just before 0.5.0 started. Going back needs that
copy, because 0.4.10 won't start on a database 0.5.0 has changed. Anything
posted after the update is lost when you go back: messages, people who
joined, rooms made. Files sent since then stay on the disk, but nothing points
at them. So decide soon if you're going to.
Go to your linger folder first:
cd ~/lingerIf you type sudo before docker commands, run sudo -s now: it keeps you
in this folder, and exit when you're done gets you out again. Then find the
copy's name; the newest is at the top:
ls -t backups/It looks like linger-0.4.10-2026-10-12-203000.tar.gz. Put its name in place
of NAME.tar.gz:
docker compose stop linger
docker compose run --rm --no-deps -T --user root --entrypoint sh linger -c 'cd /data && rm -f linger.db-wal linger.db-shm && tar xzf -' <backups/NAME.tar.gz
cp compose.yaml.before-0.5.0 compose.yaml
cp Caddyfile.before-0.5.0 Caddyfile
sed -i 's#ghcr.io/itsmattguenther/linger:latest#ghcr.io/itsmattguenther/linger:0.4.10#' compose.yaml
docker compose up -dThe second line puts the database copy back. It's the same command
update.sh prints when an update fails. The cp lines put your old files
back, and the sed line keeps you on 0.4.10, which docker compose up -d
downloads again. If your old file had a version on its image: line already,
the sed line changes nothing: open it with nano compose.yaml and make that
line image: ghcr.io/itsmattguenther/linger:0.4.10. If you moved your settings
or changed .env for this update, cp .env.before-0.5.0 .env puts it back
too. The relay goes back to its old rules and ports. Later, set the image:
line back to :latest to follow new releases again.
Install or update
Use the in-app update: Update… at the foot of the list, or Settings →
Account & App → Updates. Windows users should keep the same installer format
(.exe or .msi) when upgrading. Linux packages are .AppImage, .deb and
.rpm; on Omarchy or Arch, Linger updates with your system (Update in the
Omarchy menu, or sudo pacman -Syu). Windows installers are updater-signed,
not Authenticode-signed; SmartScreen may still warn about an unfamiliar app.
If the 0.4.10 AppImage opened an empty window for you (#479), download this
release's AppImage by hand.
On Android, download Linger_0.5.0_android-arm64.apk from this release on
the phone and install it over the old one. You stay signed in. A first install
is step by step in the 0.4.8 notes.
Older apps and servers mix fine. An app from 0.4.10 or earlier keeps
working with a 0.5.0 server, and 0.5.0 keeps working with an older server.
New things wait for the server: until it updates, there are no reaction
buttons and no Leaving soon, sign-in links and Show my local time say the
server needs updating, and polls and leaving a group DM are refused. Friends still on an older app see a
poll as its question and choices, "joined voice" and "left" as ordinary
messages, and no reactions. The one thing to avoid is changing your password
on an app older than 0.5.0 (see Safety).
New to Linger? Which file do I want?
| Your computer | Download the file ending in |
|---|---|
| Windows | -setup.exe |
| Debian, Ubuntu or Mint | .deb |
| Fedora, RHEL or openSUSE | .rpm |
| Any other Linux | .AppImage — make it executable and run it |
| macOS | Not built yet — see decisions.md |
| Android phone | _android-arm64.apk — download it on the phone |
| iPhone | Not yet |
The .msi is for companies rolling it out to many machines at once.
If you are not sure, you want the .exe.
The .sig files and latest.json are how an installed copy checks
that an update is genuine. You do not need to download them.
Windows will warn you. You get "Windows protected your PC", and
Run anyway is behind the small More info link. That is Windows
saying the installer has not been through a paid signing process. It
has not — that is a
known decision,
not a broken download.
Android will ask before installing. The phone says it won't
install apps from your browser until you allow it: tap Settings,
turn on Allow from this source, and go back. That is Android's
rule for any app that isn't from the Play Store. The phone app
doesn't update itself: install each new one from its release page,
right over the old one, and you stay signed in.
Checks on installed clients
Record OS, package type, previous and new version, and headset or microphone
with any failure. Use made-up messages, and keep private conversations out of
screenshots.
- Voice, the start of a sentence, with three or more people on 0.5.0,
across two real networks if you can: pause, then talk again, a few times
each. The first word comes through clean (#470). - Push-to-talk on Windows, in voice with push to talk on: hold the key
with a fullscreen game in front, then with Linger minimized, then with it
in the tray. Try Mouse 4 as the key (#500). - Push-to-talk on Omarchy with the Arch package: add the line Settings →
Sound & Voice shows, then hold Right Ctrl with another app in front (#500). - The tray icon, with the list in the tray: join voice (amber
microphone), mute (grey), leave (the plain door) (#601). - Sleep in voice: join, let the computer sleep more than two minutes,
wake it. The system's mic light goes off and the tray icon is the plain
door; Join brings you back (#589). - Reactions: add, take back, point at a pill for names, six on one
message. On the phone, hold a pill to see who left it (#485, #573). - Polls, as the host:
/poll, vote from several apps, close it, and let
a one-day poll run out (#474). - The joined-voice line: join and stay: one grey line. Join and leave a
few times quickly: still one line, and one chime (#473). - Leave a group DM on one device while it's open on another: its tab or
window closes there, and the others see "left" (#565). - A sign-in link: the host makes one, the friend pastes it and sets a
new password, and their other devices are signed out (#581). - Change a password on one device with the same account on another: the
other is signed out within seconds, and the first stays in (#496). - An invite link in a browser: the page shows, Copy works, and Open in
Linger opens the app with the link in its box, on the Windows installer,
on Android and on the Arch package (#578, #607). - Windows, minimized: with a Shimmer name on screen, minimize Linger and
check Task Manager; close it to the tray and bring it back a few times. It
draws properly each time (#594, #532). - Windows, the update itself: the in-app update from 0.4.10 finishes
with no "Error opening file" box (#568). - Linux: the AppImage on Mesa 26.2 with an AMD or Intel GPU shows the
app (#479). In a package, open and close conversations beside the list
many times: Linger stays open (#628). - Export: export everything, unzip, and open Open me.html in a
browser (#585). - As a host who runs the relay: after the steps above, somebody whose
network blocks UDP 3479 still gets into voice and is heard (#501, #197).