Compare commits

..

3 Commits

Author SHA1 Message Date
Neeraj Gupta
86421d5472 Bump version 2025-07-14 11:11:44 +05:30
Neeraj Gupta
4359c3f071 Merge remote-tracking branch 'origin' into release_mob_jun_25_hotfix 2025-07-14 11:10:58 +05:30
Neeraj Gupta
bab9d89d88 Bump version 2025-07-11 12:49:31 +05:30
377 changed files with 5472 additions and 17998 deletions

View File

@@ -1,22 +1,39 @@
name: Report a bug
description: Things that were working earlier but don't anymore
description: For regressions only (things that were working earlier)
labels: []
body:
- type: markdown
attributes:
value: |
**Checklist**
1. You've searched existing [issues](https://github.com/search?q=repo%3Aente-io%2Fente+&type=issues) and [discussions](https://github.com/search?q=repo%3Aente-io%2Fente+&type=discussions)
2. It was working earlier (otherwise use [enhancements](https://github.com/ente-io/ente/discussions/categories/enhancements))
3. It is not about self hosting (for those use [this](https://github.com/ente-io/ente/discussions/categories/q-a))
Before opening a new issue, **please** ensure
1. You are on the latest version,
2. You've searched for existing issues,
3. It was working earlier (otherwise use [this](https://github.com/ente-io/ente/discussions/categories/enhancements))
4. It is not about self hosting (otherwise use [this](https://github.com/ente-io/ente/discussions/categories/q-a))
- type: textarea
attributes:
label: Description
description: >
Describe the bug and steps to reproduce the behaviour, and how it
differs from the previously working behaviour.
validations:
required: true
- type: input
attributes:
label: Version
description: The version can be seen at the bottom of settings.
placeholder: e.g. v1.2.3
- type: input
attributes:
label: Last working version
description: >
The version where things were last known to be working. It is fine
if you don't remember the exact version (mention roughly then),
but **if there just isn't a last working version, then please file
it as an
[enhancement](https://github.com/ente-io/ente/discussions/categories/enhancements))**
(where the community upvotes can be used to help prioritize).
placeholder: e.g. v1.2.3
- type: dropdown
attributes:
label: What product are you using?

View File

@@ -98,7 +98,7 @@ jobs:
- name: Install appimagetool
run: |
wget -O appimagetool "https://github.com/AppImage/appimagetool/releases/download/continuous/appimagetool-x86_64.AppImage"
wget -O appimagetool "https://github.com/AppImage/AppImageKit/releases/download/continuous/appimagetool-x86_64.AppImage"
chmod +x appimagetool
mv appimagetool /usr/local/bin/

70
.github/workflows/auth-win-sign.yml vendored Normal file
View File

@@ -0,0 +1,70 @@
name: "Windows build & Sign (auth)"
on:
workflow_dispatch: # Allow manually running the action
env:
FLUTTER_VERSION: "3.24.3"
permissions:
contents: write
jobs:
build-windows:
runs-on: windows-latest
environment: "auth-win-build"
defaults:
run:
working-directory: mobile/apps/auth
steps:
- name: Checkout code and submodules
uses: actions/checkout@v4
with:
submodules: recursive
- name: Install Flutter ${{ env.FLUTTER_VERSION }}
uses: subosito/flutter-action@v2
with:
channel: "stable"
flutter-version: ${{ env.FLUTTER_VERSION }}
cache: true
- name: Create artifacts directory
run: mkdir artifacts
- name: Build Windows installer
run: |
flutter config --enable-windows-desktop
# dart pub global activate flutter_distributor
dart pub global activate --source git https://github.com/ente-io/flutter_distributor_fork --git-ref develop --git-path packages/flutter_distributor
make innoinstall
flutter_distributor package --platform=windows --targets=exe --skip-clean
mv dist/**/*-windows-setup.exe artifacts/ente-${{ github.ref_name }}-installer.exe
- name: Retain Windows EXE and DLLs
run: cp -r build/windows/x64/runner/Release ente-${{ github.ref_name }}-windows
- name: Sign files with Trusted Signing
uses: azure/trusted-signing-action@v0
with:
azure-tenant-id: ${{ secrets.AZURE_TENANT_ID }}
azure-client-id: ${{ secrets.AZURE_CLIENT_ID }}
azure-client-secret: ${{ secrets.AZURE_CLIENT_SECRET }}
endpoint: ${{ secrets.AZURE_ENDPOINT }}
trusted-signing-account-name: ${{ secrets.AZURE_CODE_SIGNING_NAME }}
certificate-profile-name: ${{ secrets.AZURE_CERT_PROFILE_NAME }}
files: |
${{ github.workspace }}/mobile/apps/auth/artifacts/ente-${{ github.ref_name }}-installer.exe
${{ github.workspace }}/mobile/apps/auth/ente-${{ github.ref_name }}-windows/auth.exe
file-digest: SHA256
timestamp-rfc3161: http://timestamp.acs.microsoft.com
timestamp-digest: SHA256
- name: Zip Windows EXE and DLLs
run: tar.exe -a -c -f artifacts/ente-${{ github.ref_name }}-windows.zip ente-${{ github.ref_name }}-windows
- name: Generate checksums
run: sha256sum artifacts/ente-* > artifacts/sha256sum-windows

View File

@@ -4,7 +4,7 @@ on:
workflow_dispatch: # Allow manually running the action
env:
FLUTTER_VERSION: "3.27.4"
FLUTTER_VERSION: "3.24.3"
permissions:
contents: write

View File

@@ -8,7 +8,7 @@ on:
- ".github/workflows/mobile-lint.yml"
env:
FLUTTER_VERSION: "3.27.4"
FLUTTER_VERSION: "3.24.3"
permissions:
contents: read

View File

@@ -9,7 +9,7 @@ on:
- "photos-v*"
env:
FLUTTER_VERSION: "3.27.4"
FLUTTER_VERSION: "3.24.3"
permissions:
contents: write

View File

@@ -1,190 +0,0 @@
name: "Internal Release V2 (photos)"
on:
workflow_dispatch: # Manual trigger only
env:
FLUTTER_VERSION: "3.27.4"
ANDROID_KEYSTORE_PATH: "keystore/ente_photos_key.jks"
jobs:
build:
runs-on: macos-15 # Required for iOS builds
environment: "ios-build"
permissions:
contents: write
defaults:
run:
working-directory: mobile/apps/photos
steps:
- name: Checkout code
uses: actions/checkout@v4
with:
submodules: recursive
- name: Install Apple Certificate
env:
MAC_OS_CERTIFICATE: ${{ secrets.MAC_OS_CERTIFICATE }}
MAC_OS_CERTIFICATE_PASSWORD: ${{ secrets.MAC_OS_CERTIFICATE_PASSWORD }}
KEYCHAIN_PASSWORD: ${{ secrets.KEYCHAIN_PASSWORD }}
run: |
# Create variables
CERTIFICATE_PATH=$RUNNER_TEMP/build_certificate.p12
KEYCHAIN_PATH=$RUNNER_TEMP/app-signing.keychain-db
# Import certificate from secrets
echo -n "$MAC_OS_CERTIFICATE" | base64 --decode -o $CERTIFICATE_PATH
# Create temporary keychain
security create-keychain -p "$KEYCHAIN_PASSWORD" $KEYCHAIN_PATH
security set-keychain-settings -lut 21600 $KEYCHAIN_PATH
security unlock-keychain -p "$KEYCHAIN_PASSWORD" $KEYCHAIN_PATH
# Import certificate to keychain
security import $CERTIFICATE_PATH -P "$MAC_OS_CERTIFICATE_PASSWORD" -A -t cert -f pkcs12 -k $KEYCHAIN_PATH
security set-key-partition-list -S apple-tool:,apple: -k "$KEYCHAIN_PASSWORD" $KEYCHAIN_PATH
# Make the keychain the default
security list-keychain -d user -s $KEYCHAIN_PATH
- name: Add provisioning profiles
run: |
# Decode and install all provisioning profiles
PROFILES_HOME="$HOME/Library/MobileDevice/Provisioning Profiles"
mkdir -p "$PROFILES_HOME"
IFS=$'\n'
for profile in ${{ secrets.MAC_OS_PROFILES_BASE64 }}; do
PROFILE_PATH="$(mktemp "$PROFILES_HOME"/$(uuidgen).mobileprovision)"
echo "$profile" | base64 --decode > "$PROFILE_PATH"
echo "Saved provisioning profile to $PROFILE_PATH"
done
# Common Setup
- name: Setup JDK 17
uses: actions/setup-java@v1
with:
java-version: 17
- name: Install Flutter
uses: subosito/flutter-action@v2
with:
flutter-version: ${{ env.FLUTTER_VERSION }}
cache: true
- name: Get Flutter dependencies
run: flutter pub get
# Android Build
- name: Setup Android signing key
uses: timheuer/base64-to-file@v1
with:
fileName: ${{ env.ANDROID_KEYSTORE_PATH }}
encodedString: ${{ secrets.SIGNING_KEY_PHOTOS }}
# - name: Build Android AAB
# run: |
# flutter build appbundle \
# --dart-define=cronetHttpNoPlay=true \
# --release \
# --flavor playstore
# env:
# SIGNING_KEY_PATH: ${{ env.ANDROID_KEYSTORE_PATH }}
# SIGNING_KEY_ALIAS: ${{ secrets.SIGNING_KEY_ALIAS_PHOTOS }}
# SIGNING_KEY_PASSWORD: ${{ secrets.SIGNING_KEY_PASSWORD_PHOTOS }}
# SIGNING_STORE_PASSWORD: ${{ secrets.SIGNING_STORE_PASSWORD_PHOTOS }}
# iOS Build (new secure implementation)
- name: Install fastlane
run: gem install fastlane
- name: Update CocoaPods Specs
run: pod repo update
working-directory: mobile/apps/photos/ios
- name: Install CocoaPods dependencies
run: |
rm -f Podfile.lock
pod install
working-directory: mobile/apps/photos/ios
- name: Create ExportOptions.plist
run: |
cat <<EOF > ios/ExportOptions.plist
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>method</key>
<string>app-store</string>
<key>teamID</key>
<string>${{ secrets.IOS_TEAM_ID }}</string>
<key>provisioningProfiles</key>
<dict>
<key>io.ente.photos</key>
<string>match AppStore io.ente.photos</string>
<key>io.ente.frame</key>
<string>match AppStore io.ente.frame</string>
<key>io.ente.frame.EntePeopleWidget</key>
<string>match AppStore io.ente.frame.EntePeopleWidget</string>
<key>io.ente.frame.EnteAlbumWidget</key>
<string>match AppStore io.ente.frame.EnteAlbumWidget</string>
<key>io.ente.frame.EnteMemoryWidget</key>
<string>match AppStore io.ente.frame.EnteMemoryWidget</string>
</dict>
</dict>
</plist>
EOF
- name: Setup App Store Connect API Key
run: |
echo '${{ secrets.IOS_API_KEY }}' > api_key.json
chmod 600 api_key.json
- name: Build iOS IPA
run: |
flutter build ipa \
--release \
--export-options-plist=ios/ExportOptions.plist \
--dart-define=cronetHttpNoPlay=true
env:
SIGNING_TEAM_ID: ${{ secrets.IOS_TEAM_ID }}
# Uploads
# - name: Upload to Play Store
# uses: r0adkll/upload-google-play@v1
# with:
# serviceAccountJsonPlainText: ${{ secrets.SERVICE_ACCOUNT_JSON }}
# packageName: io.ente.photos
# releaseFiles: build/app/outputs/bundle/playstoreRelease/app-playstore-release.aab
# track: internal
- name: Upload to TestFlight
run: |
fastlane pilot upload \
--api_key_path api_key.json \
--ipa "build/ios/ipa/Ente Photos.ipa" \
--skip_waiting_for_build_processing \
--apple_id ${{ secrets.IOS_APPLE_ID }} \
--app_identifier "io.ente.photos"
env:
APP_STORE_CONNECT_API_KEY_ID: ${{ secrets.IOS_API_KEY_ID }}
APP_STORE_CONNECT_ISSUER_ID: ${{ secrets.IOS_ISSUER_ID }}
FASTLANE_APPLE_APPLICATION_SPECIFIC_PASSWORD: ${{ secrets.IOS_APP_SPECIFIC_PASSWORD }}
- name: Clean sensitive files
run: |
rm -f api_key.json
rm -f ${{ env.ANDROID_KEYSTORE_PATH }}
- name: Notify Discord
uses: sarisia/actions-status-discord@v1
with:
webhook: ${{ secrets.DISCORD_INTERNAL_RELEASE_WEBHOOK }}
title: "🚀 Dual Platform Release Uploaded"
description: |
**Android**: [Play Store Internal](https://play.google.com/store/apps/details?id=io.ente.photos)
**iOS**: TestFlight build processing
color: 0x00ff00

View File

@@ -93,13 +93,3 @@ jobs:
accountId: ${{ secrets.CLOUDFLARE_ACCOUNT_ID }}
apiToken: ${{ secrets.CLOUDFLARE_API_TOKEN }}
command: pages deploy --project-name=ente --commit-dirty=true --branch=deploy/payments web/apps/payments/dist
- name: Build locker
run: yarn build:locker
- name: Publish locker
uses: cloudflare/wrangler-action@v3
with:
accountId: ${{ secrets.CLOUDFLARE_ACCOUNT_ID }}
apiToken: ${{ secrets.CLOUDFLARE_API_TOKEN }}
command: pages deploy --project-name=ente --commit-dirty=true --branch=deploy/locker web/apps/locker/out

View File

@@ -1,42 +1,54 @@
# Contributing
- [Spread the word](#spread-the-word)
- [Engage with the community](#engage-with-the-community)
- [Translate](#translate)
- [Document](#document)
First and foremost, thank you for your interest in contributing to Ente 🙏
There are many ways to contribute, and most of them don't require writing code.
* [Spread the word](#spread-the-word)
* [Engage with the community](#engage-with-the-community)
* [Translate](#translate)
* [Document](#document)
## Spread the word
**This is the most impactful contribution you can make**.
[Spread the word](https://help.ente.io/photos/features/referral-program/). Online on your favorite social media channels. Offline to your friends and family who are looking for a privacy-friendly alternative to big tech.
This is perhaps the most impactful contribution you can make. [Spread the
word](https://help.ente.io/photos/features/referral-program/). Online on your
favorite social media channels. Offline to your friends and family who are
looking for a privacy-friendly alternative to big tech.
## Engage with the community
Just hang around, enjoy the vibe. The Ente community — the people who are building Ente, and the people who are using Ente — hang out at various places depending on their proclivity:
Just hang around, enjoy the vibe. Answer someone's query on our
[Discord](https://discord.gg/z2YVKkycX3), or pile on in the sporadic #off-topic
rants there. Chuckle (or wince!) at our [Twitter](https://twitter.com/enteio)
memes. Suggest a new feature in our [Github
Discussions](https://github.com/ente-io/ente/discussions/new?category=enhancements),
or upvote the existing ones that you feel we should focus on first. Provide your
opinion on existing threads.
- [Discord](https://discord.ente.io)
- [Mastodon](https://fosstodon.org/@ente)
- [X / Twitter](https://twitter.com/enteio)
- [Github Discussions](https://github.com/ente-io/ente/discussions)
Just being around might seem a small thing, but it provides us energy. Knowing that there is a community of people who care for what we are building, **who want us to do better**.
These might seem like small things, but it provides us energy. Knowing that
there is a community of people who care for what we are building.
## Translate
Visit our Crowdin projects to help with translations:
If you're interested in helping out with translation, please visit our Crowdin
projects to get started:
| Project | |
| ------------- | ------------- |
| [Auth](https://crowdin.com/project/ente-authenticator-app) | [![Crowdin](https://badges.crowdin.net/ente-authenticator-app/localized.svg)](https://crowdin.com/project/ente-authenticator-app) |
| [Photos](https://crowdin.com/project/ente-photos-app) | [![Crowdin](https://badges.crowdin.net/ente-photos-app/localized.svg)](https://crowdin.com/project/ente-photos-app) |
| [Photos Web / Desktop](https://crowdin.com/project/ente-photos-web) | [![Crowdin](https://badges.crowdin.net/ente-photos-web/localized.svg)](https://crowdin.com/project/ente-photos-web) |
| Project | |
| ------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------- |
| [Auth](https://crowdin.com/project/ente-authenticator-app) | [![Crowdin](https://badges.crowdin.net/ente-authenticator-app/localized.svg)](https://crowdin.com/project/ente-authenticator-app) |
| [Photos](https://crowdin.com/project/ente-photos-app) | [![Crowdin](https://badges.crowdin.net/ente-photos-app/localized.svg)](https://crowdin.com/project/ente-photos-app) |
| [Photos Web / Desktop](https://crowdin.com/project/ente-photos-web) | [![Crowdin](https://badges.crowdin.net/ente-photos-web/localized.svg)](https://crowdin.com/project/ente-photos-web) |
If your language is not listed for translation, please [create a GitHub
issue](https://github.com/ente-io/ente/issues/new?title=Request+for+New+Language+Translation&body=Language+name%3A+%0AProject%3A+auth%2Fphotos%2Fboth)
to have it added. It is okay to have partial translations. Once ~90% of the
strings in a language get translated, we will start surfacing it in the apps.
Thank you for your support.
## Document
The help guides and FAQs for users of Ente products are also open source, and
@@ -48,9 +60,25 @@ See [docs/](docs/README.md) for how to edit these documents.
## Code contributions
If you'd like to contribute code, it is best to start small. Consider some well-scoped changes, say like adding more [custom icons to auth](auth/docs/adding-icons.md), or fixing a specific bug.
Code is a small aspect of community, and the ways mentioned above are more
important in helping us. But if you'd _really_ like to contribute code, it is
best to start small. Consider some well-scoped changes, say like adding more
[custom icons to auth](auth/docs/adding-icons.md).
Code that changes the behaviour of the product might not get merged, at least not initially. The PR can serve as a discussion bed, but you might find it easier to just start a discussion instead, or post your perspective in the (likely) existing thread about the behaviour change or new feature you wish for.
Each of the individual product/platform specific directories in this repository
have instructions on setting up a dev environment.
For anything beyond trivial bug fixes, please use
[discussions](https://github.com/ente-io/ente/discussions) instead of performing
code changes directly.
> [!TIP]
>
> Please remember that code is a important, but small, part of the overall big
> picture that makes a product a joy to use. Something that's easy in code is
> not necessarily the right choice for the product as a whole. So we'll repeat -
> there are other ways to contribute than code that we'd request you to
> consider.
## Leave a review or star

View File

@@ -26,9 +26,6 @@ export default defineConfig({
},
},
sidebar: sidebar,
outline: {
level: [2, 3],
},
socialLinks: [
{ icon: "github", link: "https://github.com/ente-io/ente/" },
{ icon: "twitter", link: "https://twitter.com/enteio" },

View File

@@ -207,22 +207,22 @@ export const sidebar = [
text: "Migration",
collapsed: true,
items: [
{ text: "Introduction", link: "/auth/migration/" },
{ text: "Introduction", link: "/auth/migration-guides/" },
{
text: "From Authy",
link: "/auth/migration/authy/",
link: "/auth/migration-guides/authy/",
},
{
text: "From Steam",
link: "/auth/migration/steam/",
link: "/auth/migration-guides/steam/",
},
{
text: "From others",
link: "/auth/migration/import",
link: "/auth/migration-guides/import",
},
{
text: "Exporting your data",
link: "/auth/migration/export",
link: "/auth/migration-guides/export",
},
],
},
@@ -239,98 +239,50 @@ export const sidebar = [
],
},
{
text: "Self-hosting",
text: "Self hosting",
collapsed: true,
items: [
{ text: "Getting started", link: "/self-hosting/" },
{
text: "Quickstart",
link: "/self-hosting/",
text: "Connecting to custom server",
link: "/self-hosting/guides/custom-server/",
},
{
text: "Installation",
collapsed: true,
items: [
{
text: "Requirements",
link: "/self-hosting/installation/requirements",
},
{
text: "Quickstart script (Recommended)",
link: "/self-hosting/installation/quickstart",
},
{
text: "Docker Compose",
link: "/self-hosting/installation/compose",
},
{
text: "Manual setup (without Docker)",
link: "/self-hosting/installation/manual",
},
{
text: "Environment variables and defaults",
link: "/self-hosting/installation/env-var",
},
{
text: "Configuration",
link: "/self-hosting/installation/config",
},
{
text: "Post-installation steps",
link: "/self-hosting/installation/post-install/",
},
{
text: "Upgrade",
link: "/self-hosting/installation/upgrade",
},
],
text: "Creating accounts",
link: "/self-hosting/creating-accounts",
},
{
text: "Administration",
collapsed: true,
items: [
{
text: "User management",
link: "/self-hosting/administration/users",
},
{
text: "Reverse proxy",
link: "/self-hosting/administration/reverse-proxy",
},
{
text: "Object storage",
link: "/self-hosting/administration/object-storage",
},
{
text: "Ente CLI",
link: "/self-hosting/administration/cli",
},
{
text: "Backup",
link: "/self-hosting/administration/backup",
},
],
text: "Configuring your server",
link: "/self-hosting/museum",
},
{
text: "Development",
collapsed: true,
items: [
{
text: "Building mobile apps",
link: "/self-hosting/development/mobile-build",
},
],
text: "Configuring S3",
link: "/self-hosting/guides/configuring-s3",
},
{
text: "Community Guides",
text: "Reverse proxy",
link: "/self-hosting/reverse-proxy",
},
{
text: "Guides",
collapsed: true,
items: [
{ text: "Introduction", link: "/self-hosting/guides/" },
{
text: "Ente via Tailscale",
link: "/self-hosting/guides/tailscale",
text: "Administering your server",
link: "/self-hosting/guides/admin",
},
{
text: "Running Ente using systemd",
link: "/self-hosting/guides/systemd",
text: "Configuring CLI for your instance",
link: "/self-hosting/guides/selfhost-cli",
},
{
text: "Running Ente from source",
link: "/self-hosting/guides/from-source",
},
{
text: "Running Ente without Docker",
link: "/self-hosting/guides/standalone-ente",
},
],
},
@@ -342,6 +294,10 @@ export const sidebar = [
text: "General",
link: "/self-hosting/troubleshooting/misc",
},
{
text: "Bucket CORS",
link: "/self-hosting/troubleshooting/bucket-cors",
},
{
text: "Uploads",
link: "/self-hosting/troubleshooting/uploads",
@@ -350,6 +306,47 @@ export const sidebar = [
text: "Docker / quickstart",
link: "/self-hosting/troubleshooting/docker",
},
{
text: "Ente CLI secrets",
link: "/self-hosting/troubleshooting/keyring",
},
],
},
{
text: "Community Guides",
collapsed: true,
items: [
{
text: "Ente via Tailscale",
link: "/self-hosting/guides/tailscale",
},
{
text: "Ente with External S3",
link: "/self-hosting/guides/external-s3",
},
],
},
{
text: "FAQ",
collapsed: true,
items: [
{ text: "General", link: "/self-hosting/faq/" },
{
text: "Verification code",
link: "/self-hosting/faq/otp",
},
{
text: "Shared albums",
link: "/self-hosting/faq/sharing",
},
{
text: "Backups",
link: "/self-hosting/faq/backup",
},
{
text: "Environment variables",
link: "/self-hosting/faq/environment",
},
],
},
],

View File

@@ -105,7 +105,8 @@ Ente Auth offers various import and export options for your codes.
automatically via the CLI.
- **Import:** Import codes from various other authentication apps.
For detailed instructions, refer to the [migration guides](../migration/).
For detailed instructions, refer to the
[migration guides](../migration-guides/).
### Deduplicate codes

View File

@@ -6,7 +6,7 @@ description: >
# Welcome!
![Ducky: Ente's Mascot](/ducky.png){width=50% style="margin: 0 auto"}
![Ducky: Ente's Mascot](/public/ducky.png){width=50% style="margin: 0 auto"}
## Introduction
@@ -14,16 +14,16 @@ Ente (pronounced en-_tay_) is a end-to-end encrypted platform for privately,
reliably, and securely storing your data on the cloud, over which 2 applications
have been developed and made available for mobile, web and desktop, namely:
- **Ente Photos** - An alternative to Google Photos and Apple Photos.
- **Ente Auth** - A free 2FA alternative to Authy.
- **Ente Photos** - An alternative to Google Photos and Apple Photos
- **Ente Auth** - A free 2FA alternative to Authy
## History
Ente was founded by Vishnu Mohandas (Ente's CEO) in response to privacy concerns
with major tech companies. The underlying motivation was the understanding that
big tech had no incentive to fix their act, but with end-to-end encrypted cross
platform apps, there was a way for people to take back control over their own
data without sacrificing on features.
Ente was the founded by Vishnu Mohandas (he's also Ente's CEO) in response to
privacy concerns with major tech companies. The underlying motivation was the
understanding that big tech had no incentive to fix their act, but with
end-to-end encrypted cross platform apps, there was a way for people to take
back control over their own data without sacrificing on features.
### Origin of the name
@@ -76,7 +76,7 @@ and stay updated:
If you encounter any issues with any of the products that's not answered by our
documentation, please reach out to our team by sending an email to
[support@ente.io](mailto:support@ente.io).
[support@ente.io](mailto:support@ente.io)
For community support, please post your queries on our
[Discord](https://discord.gg/z2YVKkycX3) server.
For community support, please post your queries on
[Discord](https://discord.gg/z2YVKkycX3)

Binary file not shown.

Before

Width:  |  Height:  |  Size: 122 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 154 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 17 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 29 KiB

View File

@@ -1,47 +0,0 @@
---
title: Backups - Self-hosting
description: General introduction to backing up your self hosted Ente instance
---
# Backing up your Ente instance
A functional Ente backend needs three things:
1. Museum (the API server)
2. Postgres (the database)
3. Object storage (any S3-compatible object storage)
Thus, when thinking about backups:
1. For Museum, you should backup your `museum.yaml`, `credentials.yaml` or any
other custom configuration that you created.
2. The entire data volume needs to be backed up for the database and object
storage.
A common oversight is taking a lot of care for backing up the object storage,
even going as far as enabling replication and backing up the the multiple object
storage volumes, but not applying the same care to the database backup.
While the actual encrypted photos are indeed stored in the object storage,
**this encrypted data will not be usable without the database** since the
database contains information like a file specific encryption key.
Viewed differently, to decrypt your data you need three pieces of information:
1. The encrypted file data itself (which comes from the object storage backup).
2. The encrypted file and collection specific encryption keys (which come from
the database backup).
3. The master key (which comes from your password).
If you're starting out with self hosting, we recommend keeping plaintext backup
of your photos.
[You can use the CLI or the desktop app to automate this](/photos/faq/export).
Once you get more comfortable with the various parts, you can try backing up
your instance.
If you rely on your instance backup, ensure that you do full restoration to
verify that you are able to access your data.
As the industry saying goes, a backup without a restore is no backup at all.

View File

@@ -1,83 +0,0 @@
---
title: Ente CLI for Self-hosted Instance - Self-hosting
description: Guide to configuring Ente CLI for Self Hosted Instance
---
# Ente CLI for self-hosted instance
If you are self-hosting, you can configure Ente CLI to export data & perform
basic administrative actions.
## Step 1: Configure endpoint
To do this, first configure the CLI to use your server's endpoint.
Define `config.yaml` and place it in `~/.ente/` or directory specified by
`ENTE_CLI_CONFIG_DIR` or directory where Ente CLI is present.
```yaml
# Set the API endpoint to your domain where Museum is being served.
endpoint:
api: http://localhost:8080
```
## Step 2: Whitelist admins
You can whitelist administrator users by following this
[guide](/self-hosting/administration/users#whitelist-admins).
## Step 3: Add an account
::: info You can not create new accounts using Ente CLI.
You can only log in to your existing accounts.
To create a new account, use Ente Photos (or Ente Auth) web application, desktop
or mobile.
:::
You can add your existing account using Ente CLI.
```shell
ente account add
```
This should prompt you for authentication details and export directory. Your
account should be added after successful authentication.
It can be used for exporting data (for plain-text backup), managing Ente Auth
and performing administrative actions.
## Step 4: Increase storage and account validity
You can use `ente admin update-subscription` to increase storage quota and
account validity (duration).
For infinite storage and validity, use the following command:
```shell
ente admin update-subscription -a <admin-user-mail> -u <user-email-to-update> --no-limit
# Set a limit
ente admin update-subscription -a <admin-user-mail> -u <user-email-to-update> --no-limit False
```
::: info The users must be registered on the server with same e-mail address.
If the commands are failing, ensure:
1. `<admin-user-mail>` is whitelisted as administrator user in `museum.yaml`.
For more information, check this
[guide](/self-hosting/administration/users#whitelist-admins).
2. `<user-email-to-update>` is a registered user with completed verification.
:::
For more information, check out the documentation for setting
[storage and account validity](https://github.com/ente-io/ente/blob/main/cli/docs/generated/ente_admin_update-subscription.md)
using the CLI.
## References
1. [Ente CLI Documentation](https://github.com/ente-io/ente/blob/main/cli/docs/generated)

View File

@@ -1,139 +0,0 @@
---
title: Configuring Object Storage - Self-hosting
description:
Configure Object Storage for storing files along with some troubleshooting
tips
---
# Configuring Object Storage
Ente relies on [S3-compatible](https://docs.aws.amazon.com/s3/) cloud storage
for storing files (photos, thumbnails and videos) as objects.
Ente ships MinIO as S3-compatible storage by default in quickstart and Docker
Compose for quick testing.
This document outlines configuration of S3 buckets and enabling replication for
further usage.
## Museum
The S3-compatible buckets have to be configured in `museum.yaml` file.
### General Configuration
Some of the common configuration that can be done at top-level are:
1. **SSL Configuration:** If you need to configure SSL (i. e., the buckets are
accessible via HTTPS), you'll need to set `s3.are_local_buckets` to `false`.
2. **Path-style URLs:** Disabling `s3.are_local_buckets` also switches to the
subdomain-style URLs for the buckets. However, some S3 providers such as
MinIO do not support this.
Set `s3.use_path_style_urls` to `true` for such cases.
### Replication
> [!IMPORTANT]
>
> Replication works only if all 3 storage buckets are configured (2 hot and 1
> cold storage).
>
> For more information, check
> [this discussion](https://github.com/ente-io/ente/discussions/3167#discussioncomment-10585970)
> and our article on ensuring [reliability](https://ente.io/reliability/).
Replication is disabled by default in self-hosted instance. Only the first
bucket (`b2-eu-cen`) is used.
Only the names are specifically fixed, you can put any other keys in
configuration body.
Use the `s3.hot_storage.primary` option if you'd like to set one of the other
pre-defined buckets as the primary bucket.
### Bucket configuration
The keys `b2-eu-cen` (primary storage), `wasabi-eu-central-2-v3` (secondary
storage) and `scw-eu-fr-v3` (cold storage) are hardcoded, however, the keys and
secret can be anything.
It has no relation to Backblaze, Wasabi or Scaleway.
Each bucket's endpoint, region, key and secret should be configured accordingly
if using an external bucket.
Additionally, you can enable SSL and path-style URL for specific buckets, which
provides flexibility for storage. If this is not configured, top level
configuration (`s3.are_local_buckets` and `s3.use_path_style_urls`) is used.
A sample configuration for `b2-eu-cen` is provided, which can be used for other
2 buckets as well:
```yaml
b2-eu-cen:
are_local_buckets: true
use_path_style_urls: true
key: <key>
secret: <secret>
endpoint: localhost:3200
region: eu-central-2
bucket: b2-eu-cen
```
## CORS (Cross-Origin Resource Sharing)
If you cannot upload a photo due to CORS error, you need to fix the CORS
configuration of your bucket.
Use the content provided below for creating a `cors.json` file:
```json
{
"CORSRules": [
{
"AllowedOrigins": ["*"],
"AllowedHeaders": ["*"],
"AllowedMethods": ["GET", "HEAD", "POST", "PUT", "DELETE"],
"MaxAgeSeconds": 3000,
"ExposeHeaders": ["Etag"]
}
]
}
```
You may have to change the `AllowedOrigins` to allow only certain origins (your
Ente web apps and Museum) for security.
Assuming you have AWS CLI on your system and that you have configured it with
your access key and secret, you can execute the below command to set bucket
CORS. Make sure to enter the right path for the `cors.json` file.
```shell
aws s3api put-bucket-cors --bucket YOUR_S3_BUCKET --cors-configuration /path/to/cors.json
```
### MinIO
Assuming you have configured an alias for MinIO account using the command:
```shell
mc alias set storage-account-alias minio-endpoint minio-key minio-secret
```
where,
1. `storage-account-alias` is a valid storage account alias name
2. `minio-endpoint` is the endpoint where MinIO is being served without the
protocol (http or https). Example: `localhost:3200`
3. `minio-key` is the MinIO username defined in `MINIO_ROOT_USER`
4. `minio-secret` is the MinIO password defined in `MINIO_PASSWORD`
To set the `AllowedOrigins` Header, you can use the following command:.
```shell
mc admin config set storage-account-alias api cors_allow_origin="*"
```
You can create also `.csv` file and dump the list of origins you would like to
allow and replace the `*` with path to the CSV file.

View File

@@ -1,101 +0,0 @@
---
Title: Configuring Reverse Proxy - Self-hosting
Description: Configuring reverse proxy for Museum and other services
---
# Reverse proxy
Reverse proxy helps in making application services accessible via the Internet
without exposing multiple ports for various services.
It also allows configuration of HTTPS through SSL certificate management.
We highly recommend using HTTPS for Museum (Ente's server). For security
reasons, Museum will not accept incoming HTTP traffic.
## Pre-requisites
1. **Reverse Proxy:** We recommend using Caddy for simplicity of configuration
and automatic certificate generation and management, although you can use
other alternatives such as NGINX, Traefik, etc.
Install Caddy using the following command on Debian/Ubuntu-based systems:
```shell
sudo apt install caddy
```
Start the service and enable it to start upon system boot.
```shell
sudo systemctl start caddy
sudo systemctl enable caddy
```
## Step 1: Configure A or AAAA records
Set up the appropriate records for the endpoints in your DNS management
dashboard (usually associated with your domain registrar).
`A` or `AAAA` records pointing to your server's IP address are sufficient.
DNS propagation can take a few minutes to take effect.
![cloudflare](/cloudflare.png)
## Step 2: Configure reverse proxy
After installing Caddy, `Caddyfile` is created at `/etc/caddy/`. Edit
`/etc/caddy/Caddyfile` to configure reverse proxies.
You can edit the minimal configuration provided below for your own needs.
> yourdomain.tld is an example. Replace it with your own domain.
```groovy
# For Museum
api.ente.yourdomain.tld {
reverse_proxy http://localhost:8080
}
# For Ente Photos web app
web.ente.yourdomain.tld {
reverse_proxy http://localhost:3000
}
# For Ente Accounts web app
accounts.ente.yourdomain.tld {
reverse_proxy http://localhost:3001
}
# For Ente Albums web app
albums.ente.yourdomain.tld {
reverse_proxy http://localhost:3002
}
# For Ente Auth web app
auth.ente.yourdomain.tld {
reverse_proxy http://localhost:3003
}
# For Ente Cast web app
cast.ente.yourdomain.tld {
reverse_proxy http://localhost:3004
}
```
## Step 3: Reload reverse proxy
Reload Caddy for changes to take effect.
```shell
sudo systemctl caddy reload
```
## Step 4: Verify the setup
Ente Photos web app should be up on https://web.ente.yourdomain.tld and Museum
at https://api.ente.yourdomain.tld.
> [!TIP] If you are using other reverse proxy servers such as NGINX, Traefik,
> etc., please check out their documentation.

View File

@@ -1,139 +0,0 @@
---
title: User Management - Self-hosting
description: Guide to configuring Ente CLI for Self Hosted Instance
---
# User Management
You may wish to self-host Ente for your family or close circle. In such cases,
you may wish to enable administrative access for few users, disable new
registrations, manage one-time tokens (OTTs), etc.
This document covers the details on how you can administer users on your server.
## Whitelist admins
The administrator users have to be explicitly whitelisted in `museum.yaml`. You
can achieve this the following steps:
1. Connect to `ente_db` (the database used for storing data related to Ente).
```shell
# Change the DB name and DB user name if you use different
# values.
# If using Docker
docker exec -it <postgres-ente-container-name>
psql -U pguser -d ente_db
# Or when using psql directly
psql -U pguser -d ente_db
```
2. Get the user ID of the first user by running the following SQL query:
```sql
SELECT * from users;
```
3. Edit `internal.admins` or `internal.admin` (if you wish to whitelist only
single user) in `museum.yaml` to add the user ID you wish to whitelist.
- For multiple admins:
```yaml
internal:
admins:
- <user_id>
```
- For single admin:
```yaml
internal:
admin: <user_id>
```
4. Restart Museum by restarting the cluster
::: tip Restart your Compose clusters whenever you make changes
If you have edited the Compose file or configuration file (`museum.yaml`), make
sure to recreate the cluster's containers.
You can do this by the following command:
```shell
docker compose down && docker compose up -d
```
:::
## Increase storage and account validity
You can use Ente CLI for increasing storage quota and account validity for users
on your instance. Check this guide for more
[information](/self-hosting/administration/cli#step-4-increase-storage-and-account-validity)
## Handle user verification codes
Ente currently relies on verification codes for completion of registration.
These are accessible in server logs. If using Docker Compose, they can be
accessed by running `sudo docker compose logs` in the cluster folder where
Compose file resides.
However, you may wish to streamline this workflow. You can follow one of the 2
methods if you wish to have many users in the system.
### Use hardcoded OTTs
You can configure to use hardcoded OTTs only for specific emails, or based on
suffix.
A sample configuration for the same is provided below, which is to be used in
`museum.yaml`:
```yaml
internal:
hardcoded-ott:
emails:
- "example@example.org,123456"
local-domain-suffix: "@example.org"
local-domain-value: 012345
```
This sets OTT to 123456 for the email address example@example.com and 012345 for
emails having @example.com as suffix.
### Send email with verification code
You can configure SMTP for sending verification code e-mails to users, which is
efficient if you do not know mail addresses of people for who you want to
hardcode OTTs or if you are serving larger audience.
Set the host and port accordingly with your credentials in `museum.yaml`
```yaml
smtp:
host:
port:
# Optional username and password if using local relay server
username:
password:
# Email address used for sending emails (this mail's credentials have to be provided)
email:
# Optional name for sender
sender-name:
```
## Disable registrations
For security purposes, you may choose to disable registrations on your instance.
You can disable new registrations by using the following configuration in
`museum.yaml`.
```yaml
internal:
disable-registration: true
```

View File

@@ -0,0 +1,27 @@
---
title: Creating accounts
description: Creating accounts on your deployment
---
# Creating accounts
Once Ente is up and running, the Ente Photos web app will be accessible on
`http://localhost:3000`. Open this URL in your browser and proceed with creating
an account.
The default API endpoint for museum will be `localhost:8080`.
![endpoint](/endpoint.png)
To complete your account registration you will need to enter a 6-digit
verification code.
This code can be found in the server logs, which should already be shown in your
quickstart terminal. Alternatively, you can open the server logs with the
following command from inside the `my-ente` folder:
```sh
sudo docker compose logs
```
![otp](/otp.png)

View File

@@ -0,0 +1,65 @@
---
title: Backups
description: General introduction to backing up your self hosted Ente instance
---
# Backing up your Ente instance
> [!WARNING]
>
> This is not meant to be a comprehensive and bullet proof guide. There are many
> moving parts, and small mistakes might make your backups unusable.
>
> Please treat this only as a general introduction. And remember to test your
> restores.
At the minimum, a functional Ente backend needs three things:
1. Museum (the API server)
2. Postgres (the database)
3. Object storage (any S3-compatible object storage)
When thinking about backups, this translates into backing up the relevant state
from each of these:
1. For museum, you'd want to backup your `museum.yaml`, `credentials.yaml` or
any other custom configuration that you created. In particular, you should
backup the
[secrets that are specific to your instance](https://github.com/ente-io/ente/blob/74377a93d8e20e969d9a2531f32f577b5f0ef090/server/configurations/local.yaml#L188)
(`key.encryption`, `key.hash` and `jwt.secret`).
2. For postgres, the entire data volume needs to be backed up.
3. For object storage, the entire data volume needs to be backed up.
A common oversight is taking a lot of care for backing up the object storage,
even going as far as enabling replication and backing up the the multiple object
storage volumes, but not applying the same care to the database backup.
While the actual encrypted photos are indeed stored in the object storage,
**this encrypted data will not be usable without the database** since the
database contains information like a file specific encryption key.
Viewed differently, to decrypt your data you need three pieces of information:
1. The encrypted file data itself (which comes from the object storage backup).
2. The ([encrypted](https://ente.io/architecture/)) file and collection specific
encryption keys (which come from the database backup).
3. The master key (which comes from your password).
---
If you're starting out with self hosting, our recommendation is to start by
keeping a plaintext backup of your photos.
[You can use the CLI or the desktop app to automate this](/photos/faq/export).
Once you get more comfortable with the various parts, you can try backing up
your instance. As a reference,
[this document outlines how Ente itself treats backups](https://ente.io/reliability).
If you stop doing plaintext backups and instead rely on your instance backup,
ensure that you do the full restore process also to verify you can get back your
data. As the industry saying goes, a backup without a restore is no backup at
all.

View File

@@ -0,0 +1,52 @@
---
title: "Environment Variables and Ports"
description:
"Information about all the Environment Variables needed to run Ente"
---
# Environment variables and ports
A self-hosted Ente instance requires specific endpoints in both Museum (the
server) and web apps. This document outlines the essential environment variables
and port mappings of the web apps.
Here's the list of important variables that a self hoster should know about:
### Museum
1. `NEXT_PUBLIC_ENTE_ENDPOINT`
The above environment variable is used to configure Museums endpoint. Where
Museum is running and which port it is listening on. This endpoint should be
configured for all the apps to connect to your self hosted endpoint.
All the apps (regardless of platform) by default connect to api.ente.io - which
is our production instance of Museum.
### Web Apps
> [!IMPORTANT] Web apps don't need to be configured with the below endpoints.
> Web app environment variables are being documented here just so that the users
> know everything in detail. Checkout
> [Configuring your Server](/self-hosting/museum) to configure endpoints for
> particular app.
In Ente, all the web apps are separate NextJS applications. Therefore, they are
all configured via environment variables. The photos app (Ente Photos) has
information about and connects to other web apps like albums, cast, etc.
1. `NEXT_PUBLIC_ENTE_ALBUMS_ENDPOINT`
This environment variable is used to configure and declare the endpoint for the
Albums web app.
## Ports
The below format is according to how ports are mapped in Docker.
Typically,`<host>:<container-port>`
1. `8080:8080`: Museum (Ente's server)
2. `3000:3000`: Ente Photos web app
3. `3001:3001`: Ente Accounts web app
4. `3003:3003`: [Ente Auth web app](https://ente.io/auth/)
5. `3004:3004`: [Ente Cast web app](http://ente.io/cast)

View File

@@ -0,0 +1,47 @@
---
title: FAQ - Self hosting
description: Frequently asked questions about self hosting Ente
---
# Frequently Asked Questions
### Do Ente Photos and Ente Auth share the same backend?
Yes. The apps share the same backend, the same database and the same object
storage namespace. The same user account works for both of them.
### Can I just self host Ente Auth?
Yes, if you wish, you can self-host the server and use it only for the 2FA auth
app. The starter Docker compose will work fine for either Photos or Auth (or
both!).
> You currently don't need to configure the S3 object storage (e.g. minio
> containers) if you're only using your self hosted Ente instance for auth.
### Can I use the server with _X_ as the object storage?
Yes. As long as whatever X you're using provides an S3 compatible API, you can
use it as the underlying object storage. For example, the starter self-hosting
Docker compose file we offer uses MinIO, and on our production deployments we
use Backblaze/Wasabi/Scaleway. But that's not the full list - as long as the
service you intend to use has a S3 compatible API, it can be used.
### How do I increase storage space for users on my self hosted instance?
See the [guide for administering your server](/self-hosting/guides/admin). In
particular, you can use the `ente admin update-subscription` CLI command to
increase the
[storage and account validity](https://github.com/ente-io/ente/blob/main/cli/docs/generated/ente_admin_update-subscription.md)
of accounts on your instance.
### How can I become an admin on my self hosted instance?
The first user you create on your instance is treated as an admin.
If you want, you can modify this behaviour by providing an explicit list of
admins in the [configuration](/self-hosting/guides/admin#becoming-an-admin).
### Can I disable registration of new accounts on my self hosted instance?
Yes. See `internal.disable-registration` in local.yaml.

View File

@@ -0,0 +1,45 @@
---
title: Verification code
description: Getting the OTP for a self hosted Ente
---
# Verification code
The self-hosted Ente by default does not send out emails, so you can pick the
verification code by:
- Getting it from the server logs, or
- Reading it from the DB (otts table)
The easiest option when getting started is to look for it in the server (museum)
logs. If you're already running the docker compose cluster using the quickstart
script, you should be already seeing the logs in your terminal. Otherwise you
can go to the folder (e.g. `my-ente`) where your `compose.yaml` is, then run
`docker compose logs museum --follow`. Once you can see the logs, look for a
line like:
```
... Skipping sending email to email@example.com: *Verification code: 112089*
```
That is the verification code.
> [!TIP]
>
> You can also configure your instance to send out emails so that you can get
> your verification code via emails by using the `smtp` section in the config.
You can also set pre-defined hardcoded OTTs for certain users when running
locally by creating a `museum.yaml` and adding the `internal.hardcoded-ott`
configuration setting to it. See
[local.yaml](https://github.com/ente-io/ente/blob/main/server/configurations/local.yaml)
in the server source code for details about how to define this.
> [!NOTE]
>
> If you're not able to get the OTP with the above methods, make sure that you
> are actually connecting to your self hosted instance and not to Ente's
> production servers. e.g. you can use the network requests tab in the browser
> console to verify that the API requests are going to your server instead of
> `api.ente.io`.

View File

@@ -0,0 +1,104 @@
---
title: Album sharing
description: Getting album sharing to work using an self-hosted Ente
---
# Is public sharing available for self-hosted instances?
Yes.
You'll need to run two instances of the web app, one is regular web app, but
another one is the same code but running on a different origin (i.e. on a
different hostname or different port).
Then, you need to tell the regular web app to use your second instance to
service public links. You can do this by setting the
`NEXT_PUBLIC_ENTE_ALBUMS_ENDPOINT` to point to your second instance when running
or building the regular web app.
For more details, see
[.env](https://github.com/ente-io/ente/blob/main/web/apps/photos/.env) and
[.env.development](https://github.com/ente-io/ente/blob/main/web/apps/photos/.env.development).
As a concrete example, assuming we have a Ente server running on
`localhost:8080`, we can start two instances of the web app, passing them
`NEXT_PUBLIC_ENTE_ALBUMS_ENDPOINT` that points to the origin
("scheme://host[:port]") of the second "albums" instance.
The first one, the normal web app
```sh
NEXT_PUBLIC_ENTE_ENDPOINT=http://localhost:8080 \
NEXT_PUBLIC_ENTE_ALBUMS_ENDPOINT=http://localhost:3002 \
yarn dev:photos
```
The second one, the same code but acting as the "albums" app (the only
difference is the port it is running on):
```sh
NEXT_PUBLIC_ENTE_ENDPOINT=http://localhost:8080 \
NEXT_PUBLIC_ENTE_ALBUMS_ENDPOINT=http://localhost:3002 \
yarn dev:albums
```
If you also want to change the prefix (the origin) in the generated public
links, to use your custom albums endpoint in the generated public link instead
of albums.ente.io, set `apps.public-albums` property in museum's configuration
For example, when running using the starter docker compose file, you can do this
by creating a `museum.yaml` and defining the following configuration there:
```yaml
apps:
public-albums: http://localhost:3002
```
(For more details, see
[local.yaml](https://github.com/ente-io/ente/blob/main/server/configurations/local.yaml)
in the server's source code).
## Dockerfile example
Here is an example of a Dockerfile by @Dylanger on our community Discord. This
runs a standalone self-hosted version of the public albums app in production
mode.
```Dockerfile
FROM node:20-alpine as builder
WORKDIR /app
COPY . .
ARG NEXT_PUBLIC_ENTE_ENDPOINT=https://your.ente.example.org
ARG NEXT_PUBLIC_ENTE_ALBUMS_ENDPOINT=https://your.albums.example.org
RUN yarn install && yarn build
FROM node:20-alpine
WORKDIR /app
COPY --from=builder /app/apps/photos/out .
RUN npm install -g serve
ENV PORT=3000
EXPOSE ${PORT}
CMD serve -s . -l tcp://0.0.0.0:${PORT}
```
Note that this only runs the public albums app, but the same principle can be
used to run both the normal Ente photos app and the public albums app. There is
a slightly more involved example showing how to do this also provided by in a
community contributed guide about
[configuring external S3](/self-hosting/guides/external-s3).
You will also want to tell museum about your custom shared albums endpoint so
that it uses that instead of the default URL when creating share links. You can
configure that in museum's `config.yaml`:
```
apps:
public-albums: https://your.albums.example.org
```

View File

@@ -0,0 +1,88 @@
---
title: Server admin
description: Administering your custom self-hosted Ente instance using the CLI
---
## Becoming an admin
By default, the first user (and only the first user) created on the system is
considered as an admin.
This facility is provided as a convenience for people who are getting started
with self hosting. For more serious deployments, we recommend creating an
explicit whitelist of admins.
> [!NOTE]
>
> The first user is only treated as the admin if the list of admins in the
> configuration is empty.
>
> Also, if at some point you delete the first user, then you will need to define
> a whitelist to make some other user as the admin if you wish (since the first
> account has been deleted).
To whitelist the user IDs that can perform admin actions on the server, use the
following steps:
- Create a `museum.yaml` in the directory where you're starting museum from. For
example, if you're running using `docker compose up`, then this file should be
in the same directory as `compose.yaml` (generally, `server/museum.yaml`).
> Docker might've created an empty `museum.yaml` _directory_ on your machine
> previously. If so, delete that empty directory and create a new file named
> `museum.yaml`.
- In this `museum.yaml` we can add overrides over the default configuration.
For whitelisting the admin userIDs we need to define an `internal.admins`. See
the "internal" section in
[local.yaml](https://github.com/ente-io/ente/blob/main/server/configurations/local.yaml)
in the server source code for details about how to define this.
Here is an example. Suppose we wanted to whitelist a user with ID
`1580559962386440`, we can create the following `museum.yaml`
```yaml
internal:
admins:
- 1580559962386440
```
You can use
[account list](https://github.com/ente-io/ente/blob/main/cli/docs/generated/ente_account_list.md)
command to find the user id of any account.
# Administering your custom server
> [!NOTE] For the first user (admin) to perform administrative actions using the
> CLI, their userID must be whitelisted in the `museum.yaml` configuration file
> under `internal.admins`. While the first user is automatically granted admin
> privileges on the server, this additional step is required for CLI operations.
You can use
[Ente's CLI](https://github.com/ente-io/ente/releases?q=tag%3Acli-v0) to
administer your self hosted server.
First we need to get your CLI to connect to your custom server. Define a
config.yaml and put it either in the same directory as CLI or path defined in
env variable `ENTE_CLI_CONFIG_PATH`
```yaml
endpoint:
api: "http://localhost:8080"
```
Now you should be able to
[add an account](https://github.com/ente-io/ente/blob/main/cli/docs/generated/ente_account_add.md),
and subsequently increase the
[storage and account validity](https://github.com/ente-io/ente/blob/main/cli/docs/generated/ente_admin_update-subscription.md)
using the CLI.
> [!NOTE]
>
> The CLI command to add an account does not create Ente accounts. It only adds
> existing accounts to the list of (existing) accounts that the CLI can use.
## Backups
See this [FAQ](/self-hosting/faq/backup).

View File

@@ -0,0 +1,123 @@
---
title: Configuring S3 buckets
description:
Configure S3 endpoints to fix upload errors or use your self hosted ente
from outside localhost
---
# Architecture
![Client, Museum, S3](/client-museum-s3.png)
There are three components involved in uploading a file:
1. The client (e.g. the web app or the mobile app)
2. Ente's server (museum)
3. The S3-compatible object storage (e.g. MinIO in the default starter)
For the uploads to work, all three of them need to be able to reach each other.
This is because the client uploads directly to the object storage.
A file upload flows as follows:
1. Client that wants to upload a file asks museum where it should upload the
file to
2. museum creates pre-signed URLs for the S3 bucket that was configured
3. Client directly uploads to the S3 buckets these URLs
4. Client finally informs museum that a file has been uploaded to this URL
The upshot of this is that _both_ the client and museum should be able to reach
your S3 bucket.
## Configuring S3
The URL for the S3 bucket is configured in
[scripts/compose/credentials.yaml](https://github.com/ente-io/ente/blob/main/server/scripts/compose/credentials.yaml#L10).
You can edit this file directly while testing, though it is more robust to
create a `museum.yaml` (in the same folder as the Docker compose file) and to
setup your custom configuration there.
> [!TIP] For more details about these configuration objects, see the
> documentation for the `s3` object in
> [configurations/local.yaml](https://github.com/ente-io/ente/blob/main/server/configurations/local.yaml).
By default, you only need to configure the endpoint for the first bucket.
The Docker compose file is shipped with MinIO as the self hosted S3 compatible
storage. By default, MinIO server is served on `localhost:3200` and the MinIO UI
on `localhost:3201`.
For example, in a localhost network situation, the way this connection works is,
museum (`1`) and MinIO (`2`) run on the same Docker network and the web app
(`3`) will also be hosted on your localhost. This enables all the three
components of the setup to communicate with each other seamlessly.
The same principle applies if you're deploying to your custom domain.
## Replication
![Replication](/replication.png)
<p align="center">Community contributed diagram of Ente's replication process</p>
> [!IMPORTANT]
>
> As of now, replication works only if all the 3 storage type needs are
> fulfilled (1 hot, 1 cold and 1 glacier storage).
>
> [Reference](https://github.com/ente-io/ente/discussions/3167#discussioncomment-10585970)
If you're wondering why there are 3 buckets on the MinIO UI - that's because our
production instance uses these to perform
[replication](https://ente.io/reliability/).
If you're also wondering about why the bucket names are specifically what they
are, it's because that is exactly what we are using on our production instance.
We use `b2-eu-cen` as hot, `wasabi-eu-central-2-v3` as cold (also the secondary
hot) and `scw-eu-fr-v3` as glacier storage. As of now, all of this is hardcoded.
Hence, the same hardcoded configuration is applied when you self host Ente.
In a self hosted Ente instance replication is turned off by default. When
replication is turned off, only the first bucket (`b2-eu-cen`) is used, and the
other two are ignored. Only the names here are specifically fixed, but in the
configuration body you can put any other keys. It does not have any relation
with `b2`, `wasabi` or even `scaleway`.
Use the `s3.hot_storage.primary` option if you'd like to set one of the other
predefined buckets as the primary bucket.
## SSL Configuration
> [!NOTE]
>
> If you need to configure SSL, you'll need to turn off `s3.are_local_buckets`
> (which disables SSL in the default starter compose template).
Disabling `s3.are_local_buckets` also switches to the subdomain style URLs for
the buckets. However, not all S3 providers support these. In particular, MinIO
does not work with these in default configuration. So in such cases you'll also
need to enable `s3.use_path_style_urls`.
## Summary
Set the S3 bucket `endpoint` in `credentials.yaml` to a `yourserverip:3200` or
some such IP / hostname that is accessible from both where you are running the
Ente clients (e.g. the mobile app) and also from within the Docker compose
cluster.
### Example
An example `museum.yaml` when you're trying to connect to museum running on your
computer from your phone on the same WiFi network:
```yaml
s3:
are_local_buckets: true
b2-eu-cen:
key: test
secret: testtest
endpoint: http://<YOUR-WIFI-IP>:3200
region: eu-central-2
bucket: b2-eu-cen
```

View File

Before

Width:  |  Height:  |  Size: 246 KiB

After

Width:  |  Height:  |  Size: 246 KiB

View File

@@ -0,0 +1,115 @@
---
title: Custom server
description: Using a custom self-hosted server with Ente client apps and CLI
---
# Connecting to a custom server
You can modify various Ente client apps and CLI to connect to a self hosted
custom server endpoint.
[[toc]]
## Mobile
The pre-built Ente apps from GitHub / App Store / Play Store / F-Droid can be
easily configured to use a custom server.
You can tap 7 times on the onboarding screen to bring up a page where you can
configure the endpoint the app should be connecting to.
![Setting a custom server on the onboarding screen](custom-server.png)
## Desktop and web
Same as the mobile app, you can tap 7 times on the onboarding screen to
configure the endpoint the app should connect to.
<div align="center">
![Setting a custom server on the onboarding screen on desktop or self-hosted web
apps](web-dev-settings.png){width=400px}
</div>
This works on both the desktop app and web app (if you deploy on your own).
To make it easier to identify when a custom server is being used, app will
thereafter show the endpoint in use (if not Ente's production server) at the
bottom of the login prompt:
![Custom server indicator on the onboarding screen](web-custom-endpoint-indicator.png)
Similarly, it'll be shown at other screens during the login flow. After login,
you can also see it at the bottom of the sidebar.
Note that the custom server configured this way is cleared when you reset the
state during logout. In particular, the app also does a reset when you press the
change email button during the login flow.
### Building from source
Alternatively (e.g. if you don't wish to configure this setting and just want to
change the endpoint the client connects to by default), you can build the app
from source and use the `NEXT_PUBLIC_ENTE_ENDPOINT` environment variable to tell
it which server to connect to. For example:
```sh
NEXT_PUBLIC_ENTE_ENDPOINT=http://localhost:8080 yarn dev:photos
```
For more details, see
[hosting the web app](https://help.ente.io/self-hosting/guides/web-app).
## CLI
> [!NOTE]
>
> You can download the CLI from
> [here](https://github.com/ente-io/ente/releases?q=tag%3Acli-v0)
Define a config.yaml and put it either in the same directory as where you run
the CLI from ("current working directory"), or in the path defined in env
variable `ENTE_CLI_CONFIG_PATH`:
```yaml
endpoint:
api: "http://localhost:8080"
```
(Another
[example](https://github.com/ente-io/ente/blob/main/cli/config.yaml.example))
## Find the hostname of your server
If you want to access your museum within your own network, you can use the
`hostname` command to find a addressable local network hostname or IP for your
computer, and then use it by suffixing it with the port number.
First, run
```sh
hostname
```
The result will look something like this
```sh
my-computer.local
```
You will need to replace the server endpoint with an address that uses your
server's hostname and the port number. Here's an example:
```
http://my-computer.local:8080
```
Note that this will only work within your network. To access it from outside the
network, you need to use the public IP or hostname.
> [!TIP]
>
> If you're having trouble uploading from your mobile app, it is likely that
> museum is not able to connect to your S3 storage. See the
> [Configuring S3](/self-hosting/guides/configuring-s3) guide for more details.

View File

Before

Width:  |  Height:  |  Size: 138 KiB

After

Width:  |  Height:  |  Size: 138 KiB

View File

@@ -0,0 +1,158 @@
---
title: DB Migration
description:
Migrating your self hosted Postgres 12 database to newer Postgres versions
---
# Migrating Postgres 12 to 15
The old sample docker compose file used Postgres 12, which is now nearing end of
life, so we've updated it to Postgres 15. Postgres major versions changes
require a migration step. This document mentions some approaches you can use.
> [!TIP]
>
> Ente itself does not use any specific Postgres 12 or Postgres 15 features, and
> will talk to either happily. It should also work with newer Postgres versions,
> but let us know if you run into any problems and we'll update this page.
### Taking a backup
`docker compose exec` allows us to run a command against a running container. We
can use it to run the `pg_dumpall` command on the postgres container to create a
plaintext backup.
Assuming your cluster is already running, and you are in the `ente/server`
directory, you can run the following (this command uses the default credentials,
you'll need to change these to match your setup):
```sh
docker compose exec postgres env PGPASSWORD=pgpass PGUSER=pguser PG_DB=ente_db pg_dumpall >pg12.backup.sql
```
This will produce a `pg12.backup.sql` in your current directory. You can open it
in a text editor (it can be huge!) to verify that it looks correct.
We won't be needing this file, this backup is recommended just in case something
goes amiss with the actual migration.
> If you need to restore from this plaintext backup, you could subsequently run
> something like:
>
> ```sh
> docker compose up postgres
> cat pg12.backup.sql | docker compose exec -T postgres env PGPASSWORD=pgpass psql -U pguser -d ente_db
> ```
## The migration
At the high level, the steps are
1. Stop your cluster.
2. Start just the postgres container after changing the image to
`pgautoupgrade/pgautoupgrade:15-bookworm`.
3. Once the in-place migration completes, stop the container, and change the
image to `postgres:15`.
#### 1. Stop the cluster
Stop your running Ente cluster.
```sh
docker compose down
```
#### 2. Run `pgautoupgrade`
Modify your `compose.yaml`, changing the image for the "postgres" container from
"postgres:12" to "pgautoupgrade/pgautoupgrade:15-bookworm"
```diff
diff a/server/compose.yaml b/server/compose.yaml
postgres:
- image: postgres:12
+ image: pgautoupgrade/pgautoupgrade:15-bookworm
ports:
```
[pgautoupgrade](https://github.com/pgautoupgrade/docker-pgautoupgrade) is a
community docker image that performs an in-place migration.
After making the change, run only the `postgres` container in the cluster
```sh
docker compose up postgres
```
The container will start and peform an in-place migration. Once it is done, it
will start postgres normally. You should see something like this is the logs
```
postgres-1 | Automatic upgrade process finished with no errors reported
...
postgres-1 | ... starting PostgreSQL 15...
```
At this point, you can stop the container (`CTRL-C`).
#### 3. Finish by changing image
Modify `compose.yaml` again, changing the image to "postgres:15".
```diff
diff a/server/compose.yaml b/server/compose.yaml
postgres:
- image: pgautoupgrade/pgautoupgrade:15-bookworm
+ image: postgres:15
ports:
```
And cleanup the temporary containers by
```sh
docker compose down --remove-orphans
```
Migration is now complete. You can start your Ente cluster normally.
```sh
docker compose up
```
## Migration elsewhere
The above instructions are for Postgres running inside docker, as the sample
docker compose file does. There are myriad other ways to run Postgres, and the
migration sequence then will depend on your exact setup.
Two common approaches are
1. Backup and restore, the `pg_dumpall` + `psql` import sequence described in
[Taking a backup](#taking-a-backup) above.
2. In place migrations using `pg_upgrade`, which is what the
[pgautoupgrade](#the-migration) migration above does under the hood.
The first method, backup and restore, is low tech and will work similarly in
most setups. The second method is more efficient, but requires a bit more
careful preparation.
As another example, here is how one can migrate 12 to 15 when running Postgres
on macOS, installed using Homebrew.
1. Stop your postgres. Make sure there are no more commands shown by
`ps aux | grep '[p]ostgres'`.
2. Install postgres15.
3. Migrate data using `pg_upgrade`:
```sh
/opt/homebrew/Cellar/postgresql@15/15.8/bin/pg_upgrade -b /opt/homebrew/Cellar/postgresql@12/12.18_1/bin -B /opt/homebrew/Cellar/postgresql@15/15.8/bin/ -d /opt/homebrew/var/postgresql@12 -D /opt/homebrew/var/postgresql@15
```
4. Start postgres 15 and verify version using `SELECT VERSION()`.

View File

@@ -0,0 +1,261 @@
---
title: External S3 buckets
description:
Self hosting Ente's server and photos web app when using an external S3
bucket
---
# Hosting server and web app using external S3
> [!NOTE]
>
> This is a community contributed guide, and some of these steps ~~might be~~
> ARE out of sync with the upstream changes. This document is retained for
> reference purposes, but if something is not working correctly, please see the
> latest [READMEs](https://github.com/ente-io/ente/blob/main/server/README.md)
> in the repository and/or other guides in [self-hosting](/self-hosting/).
This guide is for self hosting the server and the web application of Ente Photos
using docker compose and an external S3 bucket. So we assume that you already
have the keys and secrets for the S3 bucket. The plan is as follows:
1. Create a `compose.yaml` file
2. Set up the `.credentials.env` file
3. Run `docker-compose up`
4. Create an account and increase storage quota
5. Fix potential CORS issue with your bucket
## 1. Create a `compose.yaml` file
After cloning the main repository with
```bash
git clone https://github.com/ente-io/ente.git
# Or git clone git@github.com:ente-io/ente.git
cd ente
```
Create a `compose.yaml` file at the root of the project with the following
content (there is nothing to change here):
```yaml
services:
museum:
build:
context: server
args:
GIT_COMMIT: local
ports:
- 8080:8080 # API
- 2112:2112 # Prometheus metrics
depends_on:
postgres:
condition: service_healthy
# Wait for museum to ping pong before starting the webapp.
healthcheck:
test: [
"CMD",
"echo",
"1", # I don't know what to put here
]
environment:
# no need to touch these
ENTE_DB_HOST: postgres
ENTE_DB_PORT: 5432
ENTE_DB_NAME: ente_db
ENTE_DB_USER: pguser
ENTE_DB_PASSWORD: pgpass
env_file:
- ./.credentials.env
volumes:
- custom-logs:/var/logs
- museum.yaml:/museum.yaml:ro
networks:
- internal
web:
build:
context: web
ports:
- 8081:80
- 8082:80
depends_on:
museum:
condition: service_healthy
env_file:
- ./.credentials.env
postgres:
image: postgres:12
ports:
- 5432:5432
environment:
POSTGRES_USER: pguser
POSTGRES_PASSWORD: pgpass
POSTGRES_DB: ente_db
# Wait for postgres to be accept connections before starting museum.
healthcheck:
test: ["CMD", "pg_isready", "-q", "-d", "ente_db", "-U", "pguser"]
interval: 1s
timeout: 5s
retries: 20
volumes:
- postgres-data:/var/lib/postgresql/data
networks:
- internal
volumes:
custom-logs:
postgres-data:
networks:
internal:
```
It maybe be added in the future, but if it does not exist, create a `Dockerfile`
in the `web` directory with the following content:
```Dockerfile
# syntax=docker/dockerfile:1
FROM node:21-bookworm-slim as ente-builder
WORKDIR /app
RUN apt update && apt install -y ca-certificates && rm -rf /var/lib/apt/lists/*
COPY . .
RUN yarn install
ENV NEXT_PUBLIC_ENTE_ENDPOINT=DOCKER_RUNTIME_REPLACE_ENDPOINT
ENV NEXT_PUBLIC_ENTE_ALBUMS_ENDPOINT=DOCKER_RUNTIME_REPLACE_ALBUMS_ENDPOINT
RUN yarn build
FROM nginx:1.25-alpine-slim
COPY --from=ente-builder /app/apps/photos/out /usr/share/nginx/html
COPY <<EOF /etc/nginx/conf.d/default.conf
server {
listen 80 default_server;
root /usr/share/nginx/html;
location / {
try_files \$uri \$uri.html \$uri/ =404;
}
error_page 404 /404.html;
location = /404.html {
internal;
}
}
EOF
ARG ENDPOINT="http://localhost:8080"
ENV ENDPOINT "$ENDPOINT"
ARG ALBUMS_ENDPOINT="http://localhost:8082"
ENV ALBUMS_ENDPOINT "$ALBUMS_ENDPOINT"
COPY <<EOF /docker-entrypoint.d/replace_ente_endpoints.sh
echo "Replacing endpoints"
echo " Endpoint: \$ENDPOINT"
echo " Albums Endpoint: \$ALBUMS_ENDPOINT"
replace_enpoints() {
sed -i -e 's,DOCKER_RUNTIME_REPLACE_ENDPOINT,'"\$ENDPOINT"',g' \$1
sed -i -e 's,DOCKER_RUNTIME_REPLACE_ALBUMS_ENDPOINT,'"\$ALBUMS_ENDPOINT"',g' \$1
}
for jsfile in `find '/usr/share/nginx/html' -type f -name '*.js'`
do
replace_enpoints "\$jsfile"
done
EOF
RUN chmod +x /docker-entrypoint.d/replace_ente_endpoints.sh
```
This runs nginx inside to handle both the web & album URLs so we don't have to
make two web images with different port.
- `DOCKER_RUNTIME_REPLACE_ENDPOINT` this is your public museum API URL.
- `DOCKER_RUNTIME_REPLACE_ALBUMS_ENDPOINT` this is the shared albums URL (for
more details about configuring shared albums, see
[faq/sharing](/self-hosting/faq/sharing)).
Note how above we had updated the `compose.yaml` file for the server with
```yaml
web:
build:
context: web
ports:
- 8081:80
- 8082:80
```
so that web and album both point to the same container and nginx will handle it.
## 2. Set up the `.credentials.env` file
Create a `.credentials.env` file at the root of the project with the following
content (here you need to set the correct value of each variable):
<!-- The following code block should have language env, but vitepress currently
doesn't support that language, so use sh as a reasonable fallback instead. -->
```sh
# run `go run tools/gen-random-keys/main.go` in the server directory to generate the keys
ENTE_KEY_ENCRYPTION=
ENTE_KEY_HASH=
ENTE_JWT_SECRET=
# if you deploy it on a server under a domain, you need to set the correct value of the following variables
# it can be changed later
# The backend server URL (Museum) to be used by the webapp
ENDPOINT=http://localhost:8080
# The URL of the public albums webapp (also need to be updated in museum.yml so the correct links are generated)
ALBUMS_ENDPOINT=http://localhost:8082
```
Create the `museum.yaml` with additional configuration, this will be mounted
(read-only) into the container:
```yaml
s3:
are_local_buckets: false
# For some self-hosted S3 deployments you (e.g. Minio) you might need to disable bucket subdomains
use_path_style_urls: true
# The key must be named like so
b2-eu-cen:
key: $YOUR_S3_KEY
secret: $YOUR_S3_SECRET
endpoint: $YOUR_S3_ENDPOINT
region: $YOUR_S3_REGION
bucket: $YOUR_S3_BUCKET_NAME
# The same value as the one specified in ALBUMS_ENDPOINT
apps:
public-albums: http://localhost:8082
```
## 3. Run `docker-compose up`
Run `docker-compose up` at the root of the project (add `-d` to run it in the
background).
## 4. Create an account and increase storage quota
Open `http://localhost:8080` or whatever Endpoint you mentioned for the web app
and create an account. If your SMTP related configurations are all set and
right, you will receive an email with your OTT in it. There are two work arounds
to retrieve the OTP, checkout
[this document](https://help.ente.io/self-hosting/faq/otp) for getting your
OTT's..
If you successfully log in, select any plan and increase the storage quota with
the following command:
```bash
docker compose exec -i postgres psql -U pguser -d ente_db -c "INSERT INTO storage_bonus (bonus_id, user_id, storage, type, valid_till) VALUES ('self-hosted-myself', (SELECT user_id FROM users), 1099511627776, 'ADD_ON_SUPPORT', 0)"
```
After few reloads, you should see 1 To of quota.
## Related
Some other users have also shared their setups.
- [Using Traefik](https://github.com/ente-io/ente/pull/3663)
- [Building custom images from source (Linux)](https://github.com/ente-io/ente/discussions/3778)
- [Troubleshooting Bucket CORS](/self-hosting/troubleshooting/bucket-cors)

View File

@@ -0,0 +1,229 @@
---
title: Ente from Source
description: Getting started self hosting Ente Photos and/or Ente Auth
---
# Ente from Source
> [!WARNING] NOTE The below documentation will cover instructions about
> self-hosting the web app manually. If you want to deploy Ente hassle free, use
> the [one line](https://ente.io/blog/self-hosting-quickstart/) command to setup
> Ente. This guide might be deprecated in the near future.
## Installing Docker
Refer to
[How to install Docker from the APT repository](https://docs.docker.com/engine/install/ubuntu/#install-using-the-repository)
for detailed instructions.
## Start the server
```sh
git clone https://github.com/ente-io/ente
cd ente/server
docker compose up --build
```
> [!TIP]
>
> You can also use a pre-built Docker image from `ghcr.io/ente-io/server`
> ([More info](https://github.com/ente-io/ente/blob/main/server/docs/docker.md))
Install the necessary dependencies for running the web client
```sh
# installing npm and yarn
sudo apt update
sudo apt install nodejs npm
sudo npm install -g yarn // to install yarn globally
```
Then in a separate terminal, you can run (e.g) the web client
```sh
cd ente/web
git submodule update --init --recursive
yarn install
NEXT_PUBLIC_ENTE_ENDPOINT=http://localhost:8080 yarn dev
```
That's about it. If you open http://localhost:3000, you will be able to create
an account on a Ente Photos web app running on your machine, and this web app
will be connecting to the server running on your local machine at
`localhost:8080`.
For the mobile apps, you don't even need to build, and can install normal Ente
apps and configure them to use your
[custom self-hosted server](/self-hosting/guides/custom-server/).
> If you want to build the mobile apps from source, see the instructions
> [here](/self-hosting/guides/mobile-build).
## Web app with Docker and Compose
The instructoins in previous section were just a temporary way to run the web
app locally. To run the web apps as services, the user has to build a docker
image manually.
> [!IMPORTANT]
>
> Recurring changes might be made by the team or from community if more
> improvements can be made so that we are able to build a full-fledged docker
> image.
```dockerfile
FROM node:20-bookworm-slim as builder
WORKDIR ./ente
COPY . .
COPY apps/ .
# Will help default to yarn versoin 1.22.22
RUN corepack enable
# Endpoint for Ente Server
ENV NEXT_PUBLIC_ENTE_ENDPOINT=https://your-ente-endpoint.com
ENV NEXT_PUBLIC_ENTE_ALBUMS_ENDPOINT=https://your-albums-endpoint.com
RUN yarn cache clean
RUN yarn install --network-timeout 1000000000
RUN yarn build:photos && yarn build:accounts && yarn build:auth && yarn build:cast
FROM node:20-bookworm-slim
WORKDIR /app
COPY --from=builder /ente/apps/photos/out /app/photos
COPY --from=builder /ente/apps/accounts/out /app/accounts
COPY --from=builder /ente/apps/auth/out /app/auth
COPY --from=builder /ente/apps/cast/out /app/cast
RUN npm install -g serve
ENV PHOTOS=3000
EXPOSE ${PHOTOS}
ENV ACCOUNTS=3001
EXPOSE ${ACCOUNTS}
ENV AUTH=3002
EXPOSE ${AUTH}
ENV CAST=3003
EXPOSE ${CAST}
# The albums app does not have navigable pages on it, but the
# port will be exposed in-order to self up the albums endpoint
# `apps.public-albums` in museum.yaml configuration file.
ENV ALBUMS=3004
EXPOSE ${ALBUMS}
CMD ["sh", "-c", "serve /app/photos -l tcp://0.0.0.0:${PHOTOS} & serve /app/accounts -l tcp://0.0.0.0:${ACCOUNTS} & serve /app/auth -l tcp://0.0.0.0:${AUTH} & serve /app/cast -l tcp://0.0.0.0:${CAST}"]
```
The above is a multi-stage Dockerfile which creates a production ready static
output of the 4 apps (Photos, Accounts, Auth and Cast) and serves the static
content with Caddy.
Looking at 2 different node base-images doing different tasks in the same
Dockerfile would not make sense, but the Dockerfile is divided into two just to
improve the build efficiency as building this Dockerfile will arguably take more
time.
Lets build a Docker image from the above Dockerfile. Copy and paste the above
Dockerfile contents in the root of your web directory which is inside
`ente/web`. Execute the below command to create an image from this Dockerfile.
```sh
# Build the image
docker build -t <image-name>:<tag> --no-cache --progress plain .
```
You can always edit the Dockerfile and remove the steps for apps which you do
not intend to install on your system (like auth or cast) and opt out of those.
Regarding Albums App, take a note that they are not apps with navigable pages,
if accessed on the web-browser they will simply redirect to ente.web.io.
## compose.yaml
Moving ahead, we need to paste the below contents into the compose.yaml inside
`ente/server/compose.yaml` under the services section.
```yaml
ente-web:
image: <image-name> # name of the image you used while building
ports:
- 3000:3000
- 3001:3001
- 3002:3002
- 3003:3003
- 3004:3004
environment:
- NODE_ENV=development
restart: always
```
Now, we're good to go. All we are left to do now is start the containers.
```sh
docker compose up -d # --build
# Accessing the logs
docker compose logs <container-name>
```
## Configure App Endpoints
> [!NOTE] Previously, this was dependent on the env variables
> `NEXT_ENTE_PUBLIC_ACCOUNTS_ENDPOINT` and etc. Please check the below
> documentation to update your setup configurations
You can configure the web endpoints for the other apps including Accounts,
Albums Family and Cast in your `museum.yaml` configuration file. Checkout
[`local.yaml`](https://github.com/ente-io/ente/blob/543411254b2bb55bd00a0e515dcafa12d12d3b35/server/configurations/local.yaml#L76-L89)
to configure the endpoints. Make sure to setup up your DNS Records accordingly
to the similar URL's you set up in `museum.yaml`.
Next part is to configure the web server.
# Web server configuration
The last step ahead is configuring reverse_proxy for the ports on which the apps
are being served (you will have to make changes, if you have cusotmized the
ports). The web server of choice in this guide is
[Caddy](https://caddyserver.com) because with caddy you don't have to manually
configure/setup SSL ceritifcates as caddy will take care of that.
```groovy
photos.yourdomain.com {
reverse_proxy http://localhost:3001
# for logging
log {
level error
}
}
auth.yourdomain.com {
reverse_proxy http://localhost:3002
}
# and so on ...
```
Next, start the caddy server :).
```sh
# If caddy service is not enabled
sudo systemctl enable caddy
sudo systemctl daemon-reload
sudo systemctl start caddy
```
## Contributing
Please start a discussion on the Github Repo if you have any suggestions for the
Dockerfile, You can also share your setups on Github Discussions.

View File

@@ -1,5 +1,5 @@
---
title: Guides - Self-hosting
title: Self Hosting
description: Guides for self hosting Ente Photos and/or Ente Auth
---
@@ -10,12 +10,14 @@ walkthroughs, tutorials and other FAQ pages in this directory.
See the sidebar for existing guides. In particular:
- If you're just looking to get started, see installation.
- If you're just looking to get started, see
[configure custom server](custom-server/).
- For various administrative tasks, e.g. increasing the storage quota for user
on your self-hosted instance, see
[user management](/self-hosting/administration/users).
- For various admin related tasks, e.g. increasing the storage quota on your
self hosted instance, see [administering your custom server](admin).
- For configuring your S3 buckets to get the object storage to work from your
mobile device or for fixing an upload errors, see
[object storage](/self-hosting/administration/object-storage).
[configuring S3](configuring-s3). There is also a longer
[community contributed guide](external-s3) for a more self hosted setup of
both the server and web app using external S3 buckets for object storage.

View File

@@ -0,0 +1,39 @@
---
title: CLI for Self Hosted Instance
description: Guide to configuring Ente CLI for Self Hosted Instance
---
## Self Hosting
If you are self-hosting the server, you can still configure CLI to export data &
perform basic admin actions.
To do this, first configure the CLI to point to your server. Define a
config.yaml and put it either in the same directory as CLI binary or path
defined in env variable `ENTE_CLI_CONFIG_DIR`
```yaml
endpoint:
api: "http://localhost:8080"
```
You should be able to
[add an account](https://github.com/ente-io/ente/blob/main/cli/docs/generated/ente_account_add.md),
and subsequently increase the
[storage and account validity](https://github.com/ente-io/ente/blob/main/cli/docs/generated/ente_admin_update-subscription.md)
using the CLI.
For the admin actions, you first need to whitelist admin users. You can create
`server/museum.yaml`, and whitelist add the admin userID `internal.admins`. See
[local.yaml](https://github.com/ente-io/ente/blob/main/server/configurations/local.yaml#L211C1-L232C1)
in the server source code for details about how to define this.
You can use
[account list](https://github.com/ente-io/ente/blob/main/cli/docs/generated/ente_account_list.md)
command to find the user id of any account.
```yaml
internal:
admins:
# - 1580559962386440
```

View File

@@ -0,0 +1,116 @@
---
title: Installing Ente Standalone (without Docker)
description: Installing and setting up Ente standalone without docker.
---
# Installing and Deploying Ente Standalone (without Docker)
## Running Museum (Ente's server) without Docker
First, start by installing all the dependencies to get your machine ready for
development.
```sh
# For MacOS
brew tap homebrew/core
brew update
brew install go
# For Ubuntu based distros
sudo apt update && sudo apt upgrade
sudo apt install golang-go
```
Alternatively, you can also download the latest binaries from
['All Release'](https://go.dev/dl/) page from the official website.
```sh
brew install postgres@15
# Link the postgres keg
brew link postgresql@15
brew install libsodium
# For Ubuntu based distros
sudo apt install postgresql
sudo apt install libsodium23 libsodium-dev
```
The package `libsodium23` might be installed already in some cases.
Installing pkg-config
```sh
brew install pkg-config
# For Ubuntu based distros
sudo apt install pkg-config
```
## Starting Postgres
### With pg_ctl
```sh
pg_ctl -D /usr/local/var/postgres -l logfile start
```
Dependeing on the Operating System type the path for postgres binary or
configuration file might be different, please check if the command keeps failing
for you.
Ideally, if you are on a Linux system with systemd as the init. You can also
start postgres as a systemd service. After Installation execute the following
commands:
```sh
sudo systemctl enable postgresql
sudo systemctl daemon-reload && sudo systemctl start postgresql
```
### Create user
```sh
createuser -s postgres
```
## Start Museum
Start by cloning ente to your system.
```sh
git clone https://github.com/ente-io/ente
```
```sh
export ENTE_DB_USER=postgres
cd ente/server
go run cmd/museum/main.go
```
You can also add the export line to your shell's RC file, to avoid exporting the
environment variable every time.
For live reloads, install [air](https://github.com/air-verse/air#installation).
Then you can just call air after declaring the required environment variables.
For example,
```sh
ENTE_DB_USER=postgres
air
```
## Museum as a background service
Please check the below links if you want to run Museum as a service, both of
them are battle tested.
1. [How to run museum as a systemd service](https://gist.github.com/mngshm/a0edb097c91d1dc45aeed755af310323)
2. [Museum.service](https://github.com/ente-io/ente/blob/23e678889189157ecc389c258267685934b83631/server/scripts/deploy/museum.service#L4)
Once you are done with setting and running Museum, all you are left to do is run
the web app and reverse_proxy it with a webserver. You can check the following
resources for Deploying your web app.
1. [Hosting the Web App](https://help.ente.io/self-hosting/guides/web-app).
2. [Running Ente Web app as a systemd Service](https://gist.github.com/mngshm/72e32bd483c2129621ed0d74412492fd)

View File

@@ -0,0 +1,14 @@
---
title: System requirements
description: System requirements for running Ente's server
---
# System requirements
There aren't any "minimum" system requirements as such, the server process is
very light weight - it's just a single go binary, and it doesn't do any server
side ML, so I feel it should be able to run on anything reasonable.
We've used the server quite easily on small cloud instances, old laptops etc. A
community member also reported being able to run the server on
[very low-end embedded devices](https://github.com/ente-io/ente/discussions/594).

View File

@@ -1,23 +0,0 @@
---
title: Running Ente using systemd - Self-hosting
description: Running Ente services (Museum and web application) via systemd
---
# Running Ente using `systemd`
On Linux distributions using `systemd` as initialization system, Ente can be
configured to run as a background service, upon system startup by service files.
## Museum as a background service
Please check the below links if you want to run Museum as a service, both of
them are battle tested.
1. [How to run museum as a systemd service](https://gist.github.com/mngshm/a0edb097c91d1dc45aeed755af310323)
2. [Museum.service](https://github.com/ente-io/ente/blob/23e678889189157ecc389c258267685934b83631/server/scripts/deploy/museum.service#L4)
Once you are done with setting and running Museum, all you are left to do is run
the web app and set up reverse proxy. Check out the documentation for
[more information](/self-hosting/installation/manual#step-3-configure-web-application).
> **Credits:** [mngshm](https://github.com/mngshm)

View File

@@ -1,5 +1,5 @@
---
title: Self-hosting with Tailscale - Self-hosting
title: Self Hosting with Tailscale (Community)
description: Guides for self-hosting Ente Photos and/or Ente Auth with Tailscale
---
@@ -347,5 +347,3 @@ This will list all account details. Copy Acount ID.
> ente-museum-1 container from linux terminal. Run
> `docker restart ente-museum-1`. All well, now you will have 100TB storage.
> Repeat if for any other accounts you want to give unlimited storage access.
> **Credits:** [A4alli](https://github.com/A4alli)

View File

@@ -0,0 +1,195 @@
---
title: Hosting the web apps
description:
Building and hosting Ente's web apps, connecting it to your self-hosted
server
---
> [!WARNING] NOTE This page covers documentation around self-hosting the web app
> manually. If you want to deploy Ente hassle free, please use the
> [one line](https://ente.io/blog/self-hosting-quickstart/) command to setup
> Ente. This guide might be deprecated in the near future.
# Web app
The getting started instructions mention using `yarn dev` (which is an alias of
`yarn dev:photos`) to serve your web app.
> [!IMPORTANT] Please note that Ente's Web App supports the Yarn version 1.22.xx
> or 1.22.22 specifically. Make sure to install the right version or modify your
> yarn installation to meet the requirements. The user might end up into unknown
> version and dependency related errors if yarn is on different version.
```sh
cd ente/web
yarn install
NEXT_PUBLIC_ENTE_ENDPOINT=http://localhost:8080 yarn dev:photos
```
This is fine for trying the web app and verifying that your self-hosted server
is working as expected etc. But if you would like to use the web app for a
longer term, then it is recommended to follow the Docker approach.
## With Docker/Docker Compose (Recommended)
> [!IMPORTANT]
>
> Recurring changes might be made by the team or from community if more
> improvements can be made so that we are able to build a full-fledged docker
> image.
```dockerfile
FROM node:20-bookworm-slim as builder
WORKDIR ./ente
COPY . .
COPY apps/ .
# Will help default to yarn versoin 1.22.22
RUN corepack enable
# Endpoint for Ente Server
ENV NEXT_PUBLIC_ENTE_ENDPOINT=https://changeme.com
ENV NEXT_PUBLIC_ENTE_ALBUMS_ENDPOINT=https://changeme.com
RUN yarn cache clean
RUN yarn install --network-timeout 1000000000
RUN yarn build:photos && yarn build:accounts && yarn build:auth && yarn build:cast
FROM node:20-bookworm-slim
WORKDIR /app
COPY --from=builder /ente/apps/photos/out /app/photos
COPY --from=builder /ente/apps/accounts/out /app/accounts
COPY --from=builder /ente/apps/auth/out /app/auth
COPY --from=builder /ente/apps/cast/out /app/cast
RUN npm install -g serve
ENV PHOTOS=3000
EXPOSE ${PHOTOS}
ENV ACCOUNTS=3001
EXPOSE ${ACCOUNTS}
ENV AUTH=3002
EXPOSE ${AUTH}
ENV CAST=3003
EXPOSE ${CAST}
# The albums app does not have navigable pages on it, but the
# port will be exposed in-order to self up the albums endpoint
# `apps.public-albums` in museum.yaml configuration file.
ENV ALBUMS=3004
EXPOSE ${ALBUMS}
CMD ["sh", "-c", "serve /app/photos -l tcp://0.0.0.0:${PHOTOS} & serve /app/accounts -l tcp://0.0.0.0:${ACCOUNTS} & serve /app/auth -l tcp://0.0.0.0:${AUTH} & serve /app/cast -l tcp://0.0.0.0:${CAST}"]
```
The above is a multi-stage Dockerfile which creates a production ready static
output of the 4 apps (Photos, Accounts, Auth and Cast) and serves the static
content with Caddy.
Looking at 2 different node base-images doing different tasks in the same
Dockerfile would not make sense, but the Dockerfile is divided into two just to
improve the build efficiency as building this Dockerfile will arguably take more
time.
Lets build a Docker image from the above Dockerfile. Copy and paste the above
Dockerfile contents in the root of your web directory which is inside
`ente/web`. Execute the below command to create an image from this Dockerfile.
```sh
# Build the image
docker build -t <image-name>:<tag> --no-cache --progress plain .
```
You can always edit the Dockerfile and remove the steps for apps which you do
not intend to install on your system (like auth or cast) and opt out of those.
Regarding Albums App, please take a note that they are not web pages with
navigable pages, if accessed on the web-browser they will simply redirect to
ente.web.io.
## compose.yaml
Moving ahead, we need to paste the below contents into the compose.yaml inside
`ente/server/compose.yaml` under the services section.
```yaml
ente-web:
image: <image-name> # name of the image you used while building
ports:
- 3000:3000
- 3001:3001
- 3002:3002
- 3003:3003
- 3004:3004
environment:
- NODE_ENV=development
restart: always
```
Now, we're good to go. All we are left to do now is start the containers.
```sh
docker compose up -d # --build
# Accessing the logs
docker compose logs <container-name>
```
## Configure App Endpoints
> [!NOTE] Previously, this was dependent on the env variables
> `NEXT_ENTE_PUBLIC_ACCOUNTS_ENDPOINT` and etc. Please check the below
> documentation to update your setup configurations
You can configure the web endpoints for the other apps including Accounts,
Albums Family and Cast in your `museum.yaml` configuration file. Checkout
[`local.yaml`](https://github.com/ente-io/ente/blob/543411254b2bb55bd00a0e515dcafa12d12d3b35/server/configurations/local.yaml#L76-L89)
to configure the endpoints. Make sure to setup up your DNS Records accordingly
to the similar URL's you set up in `museum.yaml`.
Next part is to configure the web server.
# Web server configuration
The last step ahead is configuring reverse_proxy for the ports on which the apps
are being served (you will have to make changes, if you have cusotmized the
ports). The web server of choice in this guide is
[Caddy](https://caddyserver.com) because with caddy you don't have to manually
configure/setup SSL ceritifcates as caddy will take care of that.
```sh
photos.yourdomain.com {
reverse_proxy http://localhost:3001
# for logging
log {
level error
}
}
auth.yourdomain.com {
reverse_proxy http://localhost:3002
}
# and so on ...
```
Next, start the caddy server :).
```sh
# If caddy service is not enabled
sudo systemctl enable caddy
sudo systemctl daemon-reload
sudo systemctl start caddy
```
## Contributing
Please start a discussion on the Github Repo if you have any suggestions for the
Dockerfile, You can also share your setups on Github Discussions.

View File

@@ -1,29 +1,37 @@
---
title: Quickstart - Self-hosting
description: Getting started with self-hosting Ente
title: Self Hosting
description: Getting started self hosting Ente Photos and/or Ente Auth
---
# Quickstart
# Self Hosting
If you're looking to spin up Ente on your server, you are in the right place!
Our entire source code
([including the server](https://ente.io/blog/open-sourcing-our-server/)) is open
source. This is the same code we use on production.
For a quick preview, make sure your system meets the requirements mentioned
below. After trying the preview, you can explore other ways of self-hosting Ente
on your server as described in the documentation.
The entire source code for Ente is open source,
[including the servers](https://ente.io/blog/open-sourcing-our-server/). This is
the same code we use for our own cloud service.
## Requirements
- A system with at least 1 GB of RAM and 1 CPU core
- [Docker Compose](https://docs.docker.com/compose/)
### Hardware
> For more details, check out the
> [requirements page](/self-hosting/installation/requirements).
The server is capable of running on minimal resource requirements as a
lightweight Go binary, since most of the intensive computational tasks are done
on the client. It performs well on small cloud instances, old laptops, and even
[low-end embedded devices](https://github.com/ente-io/ente/discussions/594).
## Set up the server
### Software
#### Operating System
Any Linux or \*nix operating system, Ubuntu or Debian is recommended to have a
good Docker experience. Non-Linux operating systems tend to provide poor
experience with Docker and difficulty with troubleshooting and assistance.
#### Docker
Required for running Ente's server, web application and dependent services
(database and object storage)
## Getting started
Run this command on your terminal to setup Ente.
@@ -31,57 +39,17 @@ Run this command on your terminal to setup Ente.
sh -c "$(curl -fsSL https://raw.githubusercontent.com/ente-io/ente/main/server/quickstart.sh)"
```
This creates a directory `my-ente` in the current working directory, prompts to
start the cluster with needed containers after pulling the images required to
run Ente.
The above `curl` command pulls the Docker image, creates a directory `my-ente`
in the current working directory, prompts to start the cluster and starts all the containers required to run Ente.
::: note Make sure to modify the default values in `compose.yaml` and
`museum.yaml` if you wish to change endpoints, bucket configuration or server
configuration. :::
![quickstart](/quickstart.png)
## Try the web app
![self-hosted-ente](/web-app.webp)
Open Ente Photos web app at `http://<machine-ip>:3000` (or
`http://localhost:3000` if using on same local machine). Select **Don't have an
account?** to create a new user.
Follow the prompts to sign up.
<div style="display: flex; gap: 10px;">
<img alt="Onboarding screen" src="/onboarding.png" style="width: 50%; height: auto;">
<img alt="Sign up page" src="/sign-up.png" style="width: 50%; height: auto;">
</div>
Enter the verification code by checking the cluster logs using
`sudo docker compose logs`.
![Verification Code](/otp.png)
Upload a picture via the web user interface.
Alternatively, if using Ente Auth, get started by adding an account (assuming
you are running Ente Auth at `http://<machine-ip>:3002` or
`http://localhost:3002`).
## Try the mobile app
You can install Ente Photos from [here](/photos/faq/installing) and Ente Auth
from [here](/auth/faq/installing).
Connect to your server from
[mobile apps](/self-hosting/installation/post-install/#step-6-configure-apps-to-use-your-server).
## What next?
You may wish to install using a different way for your needs. Check the
"Installation" section for information regarding that.
You can import your pictures from Google Takeout or from other services to Ente
Photos. For more information, check out our
[migration guide](/photos/migration/) for more information.
You can import your codes from other authenticator providers to Ente Auth. Check
out our [migration guide](/auth/migration/) for more information.
> [!TIP] Important:
> If you have used quickstart for self-hosting Ente and are facing issues while > trying to run the cluster due to MinIO buckets not being created, please check [troubleshooting MinIO](/self-hosting/troubleshooting/docker#minio-provisioning-error)
>
>
## Queries?

View File

@@ -1,64 +0,0 @@
---
title: Docker Compose - Self-hosting
description: Running Ente with Docker Compose from source
---
# Docker Compose
If you wish to run Ente via Docker Compose from source, do the following:
## Requirements
Check out the [requirements](/self-hosting/installation/requirements) page to
get started.
## Step 1: Clone the repository
Clone the repository. Change into the `server/config` directory of the
repository, where the Compose file for running the cluster is present.
Run the following command for the same:
```sh
git clone https://github.com/ente-io/ente
cd ente/server/config
```
## Step 2: Populate the configuration file and environment variables
In order to run the cluster, you will have to provide environment variable
values.
Copy the configuration files for modification by the following command inside
`server/config` directory of the repository.
This allows you to modify configuration without having to face hassle while
pulling in latest changes.
```shell
# Inside the cloned repository's directory (usually `ente`)
cd server/config
cp example.env .env
cp example.yaml museum.yaml
```
Change the values present in `.env` file along with `museum.yaml` file
accordingly.
## Step 3: Start the cluster
Start the cluster by running the following command:
```sh
docker compose up --build
```
This builds Museum and web applications based on the Dockerfile and starts the
containers needed for Ente.
::: tip
Check out [post-installations steps](/self-hosting/installation/post-install/)
for further usage.
:::

View File

@@ -1,206 +0,0 @@
---
title: Configuration - Self-hosting
description:
"Information about all the configuration variables needed to run Ente with
museum.yaml"
---
# Configuration
Museum is designed to be configured either via environment variables or via
YAML. We recommend using YAML for maintaining your configuration as it can be
backed up easily, helping in restoration.
## Configuration File
Museum's configuration file (`museum.yaml`) is responsible for making database
configuration, bucket configuration, internal configuration, etc. accessible for
other internal services.
By default, Museum runs in local environment, thus `local.yaml` configuration is
loaded.
If `ENVIRONMENT` environment variable is set (say, to `production`), Museum will
attempt to load `configurations/production.yaml`.
If `credentials-file` is defined and found, it overrides the defaults.
Use `museum.yaml` file for declaring configuration over `local.yaml`.
All configuration values can be overridden via environment variables using the
`ENTE_` prefix and replacing dots (`.`) or hyphens (`-`) with underscores (`_`).
Museum reads configuration from `museum.yaml`. Any environment variables
prefixed with `ENTE_` takes precedence.
For example,
```yaml
s3:
b2-eu-cen:
endpoint:
```
in `museum.yaml` is read as `s3.b2-eu-cen.endpoint` by Museum.
`ENTE_S3_B2_EU_CEN_ENDPOINT` declared as environment variable is same as the
above and `ENTE_S3_B2_EU_CEN_ENDPOINT` overrides `s3.b2-eu-cen.endpoint`.
### General Settings
| Variable | Description | Default |
| ------------------ | --------------------------------------------------------- | ------------------ |
| `credentials-file` | Path to optional credentials override file | `credentials.yaml` |
| `credentials-dir` | Directory to look for credentials (TLS, service accounts) | `credentials/` |
| `log-file` | Log output path. Required in production. | `""` |
### HTTP
| Variable | Description | Default |
| -------------- | --------------------------------- | ------- |
| `http.use-tls` | Enables TLS and binds to port 443 | `false` |
### App Endpoints
The web apps for Ente (Auth, Cast, Albums) use different endpoints.
These endpoints are configurable in `museum.yaml` under the apps.\* section.
Upon configuration, the application will start utilizing the specified endpoints
instead of Ente's production instances or local endpoints (overridden values
used for Compose and quickstart for ease of use.)
| Variable | Description | Default |
| -------------------- | ------------------------------------------------------- | -------------------------- |
| `apps.public-albums` | Albums app base endpoint for public sharing | `https://albums.ente.io` |
| `apps.cast` | Cast app base endpoint | `https://cast.ente.io` |
| `apps.accounts` | Accounts app base endpoint (used for passkey-based 2FA) | `https://accounts.ente.io` |
### Database
| Variable | Description | Default |
| ------------- | -------------------------- | ----------- |
| `db.host` | DB hostname | `localhost` |
| `db.port` | DB port | `5432` |
| `db.name` | Database name | `ente_db` |
| `db.sslmode` | SSL mode for DB connection | `disable` |
| `db.user` | Database username | |
| `db.password` | Database password | |
| `db.extra` | Additional DSN parameters | |
### Object Storage
The `s3` section within `museum.yaml` is by default configured to use local
MinIO buckets when using `quickstart.sh` or Docker Compose.
If you wish to use an external S3 provider, you can edit the configuration with
your provider's credentials, and set `are_local_buckets` to `false`.
MinIO uses the port `3200` for API Endpoints. Web Console can be accessed at
http://localhost:3201 by enabling port `3201` in the Compose file.
If you face any issues related to uploads then check out
[CORS](/self-hosting/administration/object-storage#cors-cross-origin-resource-sharing)
and [troubleshooting](/self-hosting/troubleshooting/uploads) sections.
| Variable | Description | Default |
| -------------------------------------- | -------------------------------------------- | ------- |
| `s3.b2-eu-cen` | Primary hot storage S3 config | |
| `s3.wasabi-eu-central-2-v3.compliance` | Whether to disable compliance lock on delete | `true` |
| `s3.scw-eu-fr-v3` | Optional secondary S3 config | |
| `s3.wasabi-eu-central-2-derived` | Derived data storage | |
| `s3.are_local_buckets` | Use local MinIO-compatible storage | `false` |
| `s3.use_path_style_urls` | Enable path-style URLs for MinIO | `false` |
### Encryption Keys
These values are used for encryption of user e-mails. Default values are
provided by Museum.
They are generated by random in quickstart script, so no intervention is
necessary if using quickstart.
However, if you are using Ente for long-term needs and you have not installed
Ente via quickstart, consider generating values for these along with [JWT](#jwt)
by following the steps described below:
```shell
# If you have not cloned already
git clone https://github.com/ente-io/ente
# Generate the values
cd ente/server
go run tools/gen-random-keys/main.go
```
| Variable | Description | Default |
| ---------------- | ------------------------------ | ----------- |
| `key.encryption` | Key for encrypting user emails | Pre-defined |
| `key.hash` | Hash key | Pre-defined |
### JWT
| Variable | Description | Default |
| ------------ | ----------------------- | ---------- |
| `jwt.secret` | Secret for signing JWTs | Predefined |
### Email
| Variable | Description | Default |
| ------------------ | ---------------------------- | ------- |
| `smtp.host` | SMTP server host | |
| `smtp.port` | SMTP server port | |
| `smtp.username` | SMTP auth username | |
| `smtp.password` | SMTP auth password | |
| `smtp.email` | Sender email address | |
| `smtp.sender-name` | Custom name for email sender | |
| `transmail.key` | Zeptomail API key | |
### WebAuthn Passkey Support
| Variable | Description | Default |
| -------------------- | ---------------------------- | --------------------------- |
| `webauthn.rpid` | Relying Party ID | `localhost` |
| `webauthn.rporigins` | Allowed origins for WebAuthn | `["http://localhost:3001"]` |
### Internal
| Variable | Description | Default |
| -------------------------------------------- | --------------------------------------------- | ------- |
| `internal.silent` | Suppress external effects (e.g. email alerts) | `false` |
| `internal.health-check-url` | External healthcheck URL | |
| `internal.hardcoded-ott` | Predefined OTPs for testing | |
| `internal.hardcoded-ott.emails` | E-mail addresses with hardcoded OTTs | `[]` |
| `internal.hardcoded-ott.local-domain-suffix` | Suffix for which hardcoded OTT is to be used | |
| `internal.hardcoded-ott.local-domain-value` | Hardcoded OTT value for the above suffix | |
| `internal.admins` | List of admin user IDs | `[]` |
| `internal.admin` | Single admin user ID | |
| `internal.disable-registration` | Disable user registration | `false` |
### Replication
By default, replication of objects (photos, thumbnails, videos) is disabled and
only one bucket is used.
To enable replication, set `replication.enabled` to `true`. For this to work, 3
buckets have to be configured in total.
| Variable | Description | Default |
| -------------------------- | ------------------------------------ | ----------------- |
| `replication.enabled` | Enable replication across buckets | `false` |
| `replication.worker-url` | Cloudflare Worker for replication | |
| `replication.worker-count` | Number of goroutines for replication | `6` |
| `replication.tmp-storage` | Temp directory for replication | `tmp/replication` |
### Background Jobs
This configuration is for enabling background cron jobs for tasks such as
sending mails, removing unused objects (clean up) and worker configuration for
the same.
| Variable | Description | Default |
| --------------------------------------------- | --------------------------------------- | ------- |
| `jobs.cron.skip` | Skip all cron jobs | `false` |
| `jobs.remove-unreported-objects.worker-count` | Workers for removing unreported objects | `1` |
| `jobs.clear-orphan-objects.enabled` | Enable orphan cleanup | `false` |
| `jobs.clear-orphan-objects.prefix` | Prefix filter for orphaned objects | |

View File

@@ -1,53 +0,0 @@
---
title: Environment variables and defaults - Self-hosting
description:
"Information about all the configuration variables needed to run Ente along
with description on default configuration"
---
# Environment variables and defaults
The environment variables needed for running Ente and the default configuration
are documented below:
## Environment Variables
A self-hosted Ente instance has to specify endpoints for both Museum (the
server) and web apps.
This document outlines the essential environment variables and port mappings of
the web apps.
Here's the list of environment variables that is used by the cluster:
| Service | Environment Variable | Description | Default Value |
| ---------- | --------------------- | ----------------------------------------------------------------------------------------------- | ------------------------------- |
| `web` | `ENTE_API_ORIGIN` | Alias for `NEXT_PUBLIC_ENTE_ENDPOINT`. API Endpoint for Ente's API (Museum). | http://localhost:8080 |
| `web` | `ENTE_ALBUMS_ORIGIN` | Alias for `NEXT_PUBLIC_ENTE_ALBUMS_ENDPOINT`. Base URL for Ente Album, used for public sharing. | http://localhost:3002 |
| `postgres` | `POSTGRES_USER` | Username for PostgreSQL database | `pguser` |
| `postgres` | `POSTGRES_DB` | Name of database for use with Ente | `ente_db` |
| `postgres` | `POSTGRES_PASSWORD` | Password for PostgreSQL database's user | Randomly generated (quickstart) |
| `minio` | `MINIO_ROOT_USER` | Username for MinIO | Randomly generated (quickstart) |
| `minio` | `MINIO_ROOT_PASSWORD` | Password for MinIO | Randomly generated (quickstart) |
## Default Configuration
Self-hosted Ente clusters have certain default configuration for ease of use,
which is documented below to understand its behavior:
### Ports
The below format is according to how ports are mapped in Docker when using the
quickstart script. The mapping is of the format `<host-port>:<container-port>`
in `ports` in compose file.
| Service | Type | Host Port | Container Port |
| ------------------------------------------------------- | -------- | --------- | -------------- |
| Museum | Server | 8080 | 8080 |
| Ente Photos | Web | 3000 | 3000 |
| Ente Accounts | Web | 3001 | 3001 |
| Ente Albums | Web | 3002 | 3002 |
| [Ente Auth](https://ente.io/auth/) | Web | 3003 | 3003 |
| [Ente Cast](https://help.ente.io/photos/features/cast/) | Web | 3004 | 3004 |
| MinIO | S3 | 3200 | 3200 |
| PostgreSQL | Database | | 5432 |

View File

@@ -1,215 +0,0 @@
---
title: Manual setup (without Docker) - Self-hosting
description: Installing and setting up Ente without Docker
---
# Manual setup (without Docker)
If you wish to run Ente from source without using Docker, follow the steps
described below:
## Requirements
1. **Go:** Install Go on your system. This is needed for building Museum (Ente's
server)
```shell
sudo apt update && sudo apt upgrade
sudo apt install golang-go
```
Alternatively, you can also download the latest binaries from the
[official website](https://go.dev/dl/).
2. **PostgreSQL and `libsodium`:** Install PostgreSQL (database) and `libsodium`
(high level API for encryption) via package manager.
```shell
sudo apt install postgresql
sudo apt install libsodium23 libsodium-dev
```
Start the database using `systemd` automatically when the system starts.
```shell
sudo systemctl enable postgresql
sudo systemctl start postgresql
```
Ensure the database is running using
```shell
sudo systemctl status postgresql
```
3. **`pkg-config`:** Install `pkg-config` for dependency handling.
```shell
sudo apt install pkg-config
```
4. **yarn, npm and Node.js:** Needed for building the web application.
Install npm and Node using your package manager.
```shell
sudo apt install npm nodejs
```
Install yarn by following the
[official documentation](https://yarnpkg.com/getting-started/install)
5. **Git:** Needed for cloning the repository and pulling in latest changes
6. **Caddy:** Used for setting reverse proxy and file servers
7. **Object Storage:** Ensure you have an object storage configured for usage,
needed for storing files. You can choose to run MinIO or Garage locally
without Docker, however, an external bucket will be reliable and suited for
long-term storage.
## Step 1: Clone the repository
Start by cloning Ente's repository from GitHub to your local machine.
```shell
git clone https://github.com/ente-io/ente
```
## Step 2: Configure Museum (Ente's server)
1. Install all the needed dependencies for the server.
```shell
# Change into server directory, where the source code for Museum is
# present inside the repo
cd ente/server
# Install the needed dependencies
go mod tidy
```
2. Build the server. The server binary should be available as `./main` relative
to `server` directory
``` shell
go build cmd/museum/main.go
```
3. Create `museum.yaml` file inside `server` for configuring the needed
variables. You can copy the templated configuration file for editing with
ease.
```shell
cp config/example.yaml ./museum.yaml
```
4. Run the server
```shell
./main
```
Museum should be accessible at `http://localhost:8080`
## Step 3: Configure Web Application
1. Install the dependencies for web application. Enable corepack if prompted.
```shell
# Change into web directory, this is where all the applications
# will be managed and built
cd web
# Install dependencies
yarn install
```
2. Configure the environment variables in your corresponding shell's
configuration file (`.bashrc`, `.zshrc`)
```shell
# Replace this with actual endpoint for Museum
export NEXT_PUBLIC_ENTE_ENDPOINT=http://localhost:8080
# Replace this with actual endpoint for Albums
export NEXT_PUBLIC_ENTE_ALBUMS_ENDPOINT=http://localhost:3002
```
3. Build the needed applications (Photos, Accounts, Auth, Cast) as per your
needs:
```shell
# These commands are executed inside web directory
# Build photos. Build output to be served is present at apps/photos/out
yarn build
# Build accounts. Build output to be served is present at apps/accounts/out
yarn build:accounts
# Build auth. Build output to be served is present at apps/auth/out
yarn build:auth
# Build cast. Build output to be served is present at apps/cast/out
yarn build:cast
```
4. Copy the output files to `/var/www/ente/apps` for easier management.
```shell
mkdir -p /var/www/ente/apps
# Photos
sudo cp -r apps/photos/out /var/www/ente/apps/photos
# Accounts
sudo cp -r apps/accounts/out /var/www/ente/apps/accounts
# Auth
sudo cp -r apps/auth/out /var/www/ente/apps/auth
# Cast
sudo cp -r apps/cast/out /var/www/ente/apps/cast
```
5. Set up file server using Caddy by editing `Caddyfile`, present at
`/etc/caddy/Caddyfile`.
```groovy
# Replace the ports with domain names if you have subdomains configured and need HTTPS
:3000 {
root * /var/www/ente/apps/out/photos
file_server
try_files {path} {path}.html /index.html
}
:3001 {
root * /var/www/ente/apps/out/accounts
file_server
try_files {path} {path}.html /index.html
}
:3002 {
root * /var/www/ente/apps/out/photos
file_server
try_files {path} {path}.html /index.html
}
:3003 {
root * /var/www/ente/apps/out/auth
file_server
try_files {path} {path}.html /index.html
}
:3004 {
root * /var/www/ente/apps/out/cast
file_server
try_files {path} {path}.html /index.html
}
```
The web application for Ente Photos should be accessible at
http://localhost:3000, check out the
[default ports](/self-hosting/installation/env-var#ports) for more
information.
::: tip
Check out [post-installations steps](/self-hosting/installation/post-install/)
for further usage.
:::

View File

@@ -1,172 +0,0 @@
---
title: Post-installation steps - Self-hosting
description: Steps to be followed post-installation for smooth experience
---
# Post-installation steps
A list of steps that should be done after installing Ente are described below:
## Step 1: Creating first user
The first user to be created will be treated as an admin user by default.
Once Ente is up and running, the Ente Photos web app will be accessible on
`http://localhost:3000`.
Select **Don't have an account?** to create a new user. Follow the prompts to
sign up.
<div style="display: flex; gap: 10px;">
<img alt="Onboarding screen" src="/onboarding.png" style="width: 50%; height: auto;">
<img alt="Sign up page" src="/sign-up.png" style="width: 50%; height: auto;">
</div>
Enter the verification code to complete registration.
This code can be found in the server logs, which should be shown in your
terminal where you started the Docker Compose cluster.
If not, access the server logs inside the folder where Compose file resides.
```shell
sudo docker compose logs
```
If running Museum without Docker, the code should be visible in the terminal
(stdout).
![otp](/otp.png)
## Step 2: Whitelist admins
1. Connect to `ente_db` (the database used for storing data related to Ente).
```shell
# Change the DB name and DB user name if you use different
# values.
# If using Docker docker exec -it <postgres-ente-container-name>
psql -U pguser -d ente_db
# Or when using psql directly
psql -U pguser -d ente_db
```
2. Get the user ID of the first user by running the following PSQL command:
```sql
SELECT * from users;
```
3. Edit `internal.admins` or `internal.admin` (if you wish to whitelist only
single user) in `museum.yaml` to add the user ID you wish to whitelist.
- For multiple admins:
```yaml
internal:
admins:
- <user_id>
```
- For single admin:
```yaml
internal:
admin: <user_id>
```
4. Restart Museum by restarting the cluster
::: tip Restart your Compose clusters whenever you make changes
If you have edited the Compose file or configuration file (`museum.yaml`), make
sure to recreate the cluster's containers.
You can do this by the following command:
```shell
docker compose down && docker compose up -d
```
:::
## Step 3: Configure application endpoints
You may wish to access some of the applications such as Auth, Albums, Cast via
your instance's endpoints through the application instead of our production
instances.
You can do so by editing the `apps` section in `museum.yaml` to use the base
endpoints of the corresponding web applications.
```yaml
# Replace yourdomain.tld with actual domain
apps:
public-albums: https://albums.ente.yourdomain.tld
cast: https://cast.ente.yourdomain.tld
auth: https://auth.ente.yourdomain.tld
```
## Step 4: Make it publicly accessible
You may wish to access Ente on public Internet. You can do so by configuring a
reverse proxy with software such as Caddy, NGINX, Traefik.
Check out our [documentation](/self-hosting/administration/reverse-proxy) for
more information.
If you do not wish to make it accessible via Internet, we recommend you to use
[Tailscale](/self-hosting/guides/tailscale) for convenience. Alternately, you
can use your IP address for accessing the application in your local network,
though this poses challenges with respect to object storage.
## Step 5: Download mobile and desktop app
You can install Ente Photos by following the
[installation section](/photos/faq/installing).
You can also install Ente Auth (if you are planning to use Auth) by following
the [installation section](/auth/faq/installing).
## Step 6: Configure apps to use your server
You can modify Ente mobile apps and CLI to connect to your server.
### Mobile
Tap the onboarding screen 7 times to modify developer settings. Enter your Ente
server's endpoint.
<div style="display: flex; gap: 10px;">
<img src="/developer-settings.png" alt="Developer Settings" height="50%" width="50%" />
<img src="/developer-settings-endpoint.png" alt="Developer Settings - Server Endpoint" height="50%" width="50%" />
</div>
### Desktop
Tap 7 times on the onboarding screen to configure the server endpoint to be
used.
<div align="center">
![Setting a custom server on the onboarding screen on desktop or self-hosted web
apps](web-dev-settings.png){width=400px}
</div>
## Step 7: Configure Ente CLI
You can download Ente CLI from
[here](https://github.com/ente-io/ente/releases?q=tag%3Acli)
Check our [documentation](/self-hosting/administration/cli) on how to use Ente
CLI for managing self-hosted instances.
::: info For upgrading
Check out our [upgrading documentation](/self-hosting/installation/upgrade) for
various installation methods.
:::

View File

@@ -1,42 +0,0 @@
---
title: Quickstart script (Recommended) - Self-hosting
description: Self-hosting Ente with quickstart script
---
# Quickstart script (Recommended)
We provide a quickstart script which can be used for self-hosting Ente on your
machine in less than a minute.
## Requirements
Check out the [requirements](/self-hosting/installation/requirements) page to
get started.
## Getting started
Run this command on your terminal to setup Ente.
```sh
sh -c "$(curl -fsSL https://raw.githubusercontent.com/ente-io/ente/main/server/quickstart.sh)"
```
The above `curl` command does the following:
1. Creates a directory `./my-ente` in working directory.
2. Starts the containers required to run Ente upon prompting.
You should be able to access the web application at
[http://localhost:3000](http://localhost:3000) or
[http://machine-ip:3000](http://<machine-ip>:3000)
The data accessed by Museum is stored in `./data` folder inside `my-ente`
directory. It contains extra configuration files that is to be used (push
notification credentials, etc.)
::: tip
Check out [post-installation steps](/self-hosting/installation/post-install/)
for further usage.
:::

View File

@@ -1,41 +0,0 @@
---
title: Requirements - Self-hosting
description: Requirements for self-hosting Ente
---
# Requirements
Ensure your system meets these requirements and has the needed software
installed for a smooth experience.
## Hardware
The server is capable of running on minimal resource requirements as a
lightweight Go binary, since most of the intensive computational tasks are done
on the client. It performs well on small cloud instances, old laptops, and even
[low-end embedded devices](https://github.com/ente-io/ente/discussions/594).
- **Storage:** An Unix-compatible filesystem such as ZFS, EXT4, BTRFS, etc. if
using PostgreSQL container as it requires a filesystem that supports
user/group permissions.
- **RAM:** A minimum of 1 GB of RAM is required for running the cluster (if
using quickstart script).
- **CPU:** A minimum of 1 CPU core is required.
## Software
- **Operating System:** Any Linux or \*nix operating system, Ubuntu or Debian is
recommended to have a good Docker experience. Non-Linux operating systems tend
to provide poor experience with Docker and difficulty with troubleshooting and
assistance.
- **Docker:** Required for running Ente's server, web application and dependent
services (database and object storage). Ente also requires **Docker Compose
plugin** to be installed.
> [!NOTE]
>
> Ente requires **Docker Compose version 2.30 or higher**.
>
> Furthermore, Ente uses the command `docker compose`, `docker-compose` is no
> longer supported.

View File

@@ -1,77 +0,0 @@
---
title: Upgrade - Self-hosting
description: Upgrading self-hosted Ente
---
# Upgrade your server
Upgrading Ente depends on the method of installation you have chosen.
## Quickstart
::: tip For Docker users
You can free up some disk space by deleting older images that were used by
obsolette containers.
```shell
docker image prune
```
:::
Pull in the latest images in the directory where the Compose file resides.
Restart the cluster to recreate containers with newer images.
Run the following command inside `my-ente` directory (default name used in
quickstart):
```shell
docker compose pull && docker compose up -d
```
## Docker Compose
You can pull in the latest source code from Git and build a new cluster based on
the updated source code.
1. Pull the latest changes from `main`.
```shell
# Assuming you have cloned repository to ente
cd ente
# Pull changes
git pull
```
2. Recreate the cluster.
```shell
cd server/config
# Stop and remove containers if they are running
docker compose down
# Build with latest code
docker compose up --build
```
## Manual Setup
You can pull in the latest source code from Git and build a new cluster based on
the updated source code.
1. Pull the latest changes from `main`.
```shell
# Assuming you have cloned repository to ente
cd ente
# Pull changes and only keep changes from remote.
# This is needed to keep yarn.lock up-to-date.
# This resets all changes made in the local repository.
# Make sure to stash changes if you have made any.
git fetch origin
git reset --hard main
```
2. Follow the steps described in
[manual setup](/self-hosting/installation/manual#step-3-configure-web-application)
for Museum and web applications.

View File

@@ -0,0 +1,77 @@
---
title: Configuring your server
description: Guide to writing a museum.yaml
---
# Configuring your server
Ente's monolithic server is called **museum**.
`museum.yaml` is a YAML configuration file used to configure museum. By default,
[`local.yaml`](https://github.com/ente-io/ente/tree/main/server/configurations/local.yaml)
is provided, but its settings are overridden with those from `museum.yaml`.
If you used our quickstart script, your `my-ente` directory will include a
`museum.yaml` file with preset configurations for encryption keys, secrets,
PostgreSQL and MinIO.
> [!TIP]
>
> Always do `docker compose down` inside your `my-ente` directory. If you've
> made changes to `museum.yaml`, restart the containers with
> `docker compose up -d ` to see your changes in action.
## S3 buckets
The `s3` section within `museum.yaml` is by default configured to use local
MinIO buckets.
If you wish to use an external S3 provider, you can edit the configuration with
your provider's credentials, and set `are_local_buckets` to `false`.
Check out [Configuring S3](/self-hosting/guides/configuring-s3.md) to understand
more about configuring S3 buckets.
MinIO uses the port `3200` for API Endpoints and their web app runs over
`:3201`. You can login to MinIO Web Console by opening `localhost:3201` in your
browser.
If you face any issues related to uploads then checkout
[Troubleshooting bucket CORS](/self-hosting/troubleshooting/bucket-cors) and
[Frequently encountered S3 errors](/self-hosting/guides/configuring-s3#frequently-encountered-errors).
## Web apps
The web apps for Ente Photos is divided into multiple sub-apps like albums,
cast, auth, etc. These endpoints are configurable in `museum.yaml` under the
`apps.*` section.
For example,
```yaml
apps:
public-albums: https://albums.myente.xyz
cast: https://cast.myente.xyz
accounts: https://accounts.myente.xyz
family: https://family.myente.xyz
```
> [!IMPORTANT] By default, all the values redirect to our publicly hosted
> production services. For example, if `public-albums` is not configured your
> shared album will use the `albums.ente.io` URL.
After you are done with filling the values, restart museum and the app will
start utilizing those endpoints instead of Ente's production instances.
Once you have configured all the necessary endpoints, `cd` into `my-ente` and
stop all the Docker containers with `docker compose down` and restart them with
`docker compose up -d`.
Similarly, you can use the default
[`local.yaml`](https://github.com/ente-io/ente/tree/main/server/configurations/local.yaml)
as a reference for building a functioning `museum.yaml` for many other
functionalities like SMTP, Discord notifications, Hardcoded-OTTs, etc.
## References
- [Environment variables and ports](/self-hosting/faq/environment)

View File

@@ -0,0 +1,53 @@
---
Title: Configuring Reverse Proxy
Description: configuring reverse proxy for Museum and other endpoints
---
# Reverse proxy
Ente's server (museum) runs on port `:8080`, web app on `:3000` and the other
apps from ports `3001-3004`.
We highly recommend using HTTPS for Museum (`8080`). For security reasons museum
will not accept incoming HTTP traffic.
Head over to your DNS management dashboard and setup the appropriate records for
the endpoints. Mostly, `A` or `AAAA` records targeting towards your server's IP
address should be sufficient. The rest of the work will be done by the web
server on your machine.
![cloudflare](/cloudflare.png)
### Caddy
Setting up a reverse proxy with Caddy is easy and straightforward.
Firstly, install Caddy on your server.
```sh
sudo apt install caddy
```
After the installation is complete, a `Caddyfile` is created on the path
`/etc/caddy/`. This file is used to configure reverse proxies among other
things.
```groovy
# Caddyfile - myente.xyz is just an example.
api.myente.xyz {
reverse_proxy http://localhost:8080
}
ente.myente.xyz {
reverse_proxy http://localhost:3000
}
#...and so on for other endpoints
```
After a hard-reload, the Ente Photos web app should be up on
https://ente.myente.xyz.
If you are using a different tool for reverse proxy (like nginx), please check
out their documentation.

View File

@@ -0,0 +1,70 @@
---
title: Bucket CORS
description: Troubleshooting CORS issues with S3 Buckets
---
# Fix potential CORS issues with your Buckets
## For AWS S3
If you cannot upload a photo due to a CORS issue, you need to fix the CORS
configuration of your bucket.
Create a `cors.json` file with the following content:
```json
{
"CORSRules": [
{
"AllowedOrigins": ["*"],
"AllowedHeaders": ["*"],
"AllowedMethods": ["GET", "HEAD", "POST", "PUT", "DELETE"],
"MaxAgeSeconds": 3000,
"ExposeHeaders": ["Etag"]
}
]
}
```
You may want to change the `AllowedOrigins` to a more restrictive value.
If you are using AWS for S3, you can execute the below command to get rid of
CORS. Make sure to enter the right path for the `cors.json` file.
```bash
aws s3api put-bucket-cors --bucket YOUR_S3_BUCKET --cors-configuration /path/to/cors.json
```
## For Self-hosted Minio Instance
::: warning
- MinIO does not support bucket CORS in the community edition which is used by
default. For more information, check
[this discussion](https://github.com/minio/minio/discussions/20841). However,
global CORS configuration is possible.
- MinIO does not take JSON CORS file as the input, instead you will have to
build a CORS.xml file or just convert the above `cors.json` to XML.
:::
A minor requirement here is the tool `mc` for managing buckets via command line
interface. Checkout the `mc set alias` document to configure alias for your
instance and bucket. After this you will be prompted for your AccessKey and
Secret, which is your username and password.
```sh
mc cors set <your-minio>/<your-bucket-name /path/to/cors.xml
```
or, if you just want to just set the `AllowedOrigins` Header, you can use the
following command to do so.
```sh
mc admin config set <your-minio>/<your-bucket-name> api cors_allow_origin="*"
```
You can create also `.csv` file and dump the list of origins you would like to
allow and replace the `*` with `path` to the CSV file.
Now, uploads should be working fine.

View File

@@ -1,19 +1,19 @@
---
title: Troubleshooting Docker-related errors - Self-hosting
description: Fixing Docker-related errors when trying to self-host Ente
title: Docker Errors
description: Fixing docker related errors when trying to self host Ente
---
# Troubleshooting Docker-related errors
# Docker
> [!TIP] Restart after changes
>
> Remember to restart your cluster to ensure changes that you make in the
> `compose.yaml` and `museum.yaml` get picked up.
>
> ```shell
> docker compose down
> docker compose up
> ```
## configs
Remember to restart your cluster to ensure changes that you make in the
`configs` section in `compose.yaml` get picked up.
```sh
docker compose down
docker compose up
```
## post_start
@@ -45,12 +45,15 @@ minio-provision:
entrypoint: |
sh -c '
#!/bin/sh
while ! mc alias set h0 http://minio:3200 your_minio_user your_minio_pass
do
echo "waiting for minio..."
sleep 0.5
done
cd /data
mc mb -p b2-eu-cen
mc mb -p wasabi-eu-central-2-v3
mc mb -p scw-eu-fr-v3
@@ -87,54 +90,57 @@ museum-1 | /etc/ente/cmd/museum/main.go:124 +0x44c
museum-1 exited with code 2
```
Then the issue is that the password you're using is not the password PostgreSQL
is expecting.
Then the issue is that the password you're using is not the password postgres is
expecting (duh), and a potential scenario where that can happen is something
like this:
There are 2 possibilities:
1. On a machine, you create a new cluster with `quickstart.sh`.
1. When you have created a cluster in `my-ente` directory on running
`quickstart.sh` and later deleted it, only to create another cluster with
same `my-ente` directory.
2. Later you delete that folder, but then create another cluster with
`quickstart.sh`. Each time `quickstart.sh` runs, it creates new credentials,
and then when it tries to spin up the docker compose cluster, use them to
connect to the postgres running within.
However, by deleting the directory, the Docker volumes are not deleted.
3. However, you would already have a docker volume from the first run of
`quickstart.sh`. Since the folder name is the same in both cases `my-ente`,
Docker will reuse the existing volumes (`my-ente_postgres-data`,
`my-ente_minio-data`). So your postgres is running off the old credentials,
and you're trying to connect to it using the new ones, and the error arises.
Thus the older volumes with previous cluster's credentials are used for new
cluster and the error arises.
The solution is to delete the stale docker volume. **Be careful**, this will
delete all data in those volumes (any thing you uploaded etc), so first
understand if this is the exact problem you are facing before deleting those
volumes.
Deletion of the stale Docker volume can solve this. **Be careful**, this
will delete all data in those volumes (any thing you uploaded etc). Do this
if you are sure this is the exact problem.
If you're sure of what you're doing, the volumes can be deleted by
```shell
docker volume ls
```
```sh
docker volume ls
```
to list them, and then delete the ones that begin with `my-ente` using
`docker volume rm`. You can delete all stale volumes by using
`docker system prune` with the `--volumes` flag, but be _really_ careful,
that'll delete all volumes (Ente or otherwise) on your machine that are not
currently in use by a running Docker container.
to list them, and then delete the ones that begin with `my-ente` using
`docker volume rm`. You can delete all stale volumes by using
`docker system prune` with the `--volumes` flag, but be _really_ careful,
that'll delete all volumes (Ente or otherwise) on your machine that are not
currently in use by a running docker container.
An alternative way is to delete the volumes along with removal of cluster's
containers using `docker compose` inside `my-ente` directory.
An alternative way is to delete the volumes along with removal of cluster's
containers using `docker compose` inside `my-ente` directory.
```sh
docker compose down --volumes
```
```sh
docker compose down --volumes
```
If you're unsure about removing volumes, another alternative is to rename
your `my-ente` folder. Docker uses the folder name to determine the volume
name prefix, so giving it a different name will cause Docker to create a
volume afresh for it.
If you're unsure about removing volumes, another alternative is to rename your
`my-ente` folder. Docker uses the folder name to determine the volume name
prefix, so giving it a different name will cause Docker to create a volume
afresh for it.
## MinIO provisioning error
MinIO has deprecated the `mc config` command in favor of `mc alias set`
resulting in failure in execution of the command for creating bucket using
`post_start` hook.
If you have used our quickstart script for self-hosting Ente (new users will be unaffected) and are using the default MinIO container for object storage, you may run into issues while starting the cluster after pulling latest images with provisioning MinIO and creating buckets.
You may encounter similar logs while trying to start the cluster if you are
using the older command (provided by default in `quickstart.sh`):
You may encounter similar logs while trying to start the cluster:
```
my-ente-minio-1 -> | Waiting for minio...
@@ -142,27 +148,30 @@ my-ente-minio-1 -> | Waiting for minio...
my-ente-minio-1 -> | Waiting for minio...
```
This can be resolved by changing
`mc config host h0 add http://minio:3200 $minio_user $minio_pass` to
`mc alias set h0 http://minio:3200 $minio_user $minio_pass`
MinIO has deprecated the `mc config` command in favor of `mc alias set` resulting in failure in execution of the command for creating bucket using `post_start` hook.
This can be resolved by changing `mc config host h0 add http://minio:3200 $minio_user $minio_pass` to `mc alias set h0 http://minio:3200 $minio_user $minio_pass`
Thus the updated `post_start` will look as follows for `minio` service:
```yaml
minio:
``` yaml
minio:
...
post_start:
- command: |
sh -c '
#!/bin/sh
while ! mc alias set h0 http://minio:3200 your_minio_user your_minio_pass 2>/dev/null
do
echo "Waiting for minio..."
sleep 0.5
done
cd /data
mc mb -p b2-eu-cen
mc mb -p wasabi-eu-central-2-v3
mc mb -p scw-eu-fr-v3
'
```
```

View File

@@ -1,5 +1,5 @@
---
title: Ente CLI Secrets - Self-hosting
title: Ente CLI Secrets
description: A quick hotfix for keyring errors while running Ente CLI.
---
@@ -13,8 +13,9 @@ Follow the below steps to run Ente CLI and also avoid keyrings errors.
Run:
```shell
```sh
# export the secrets path
export ENTE_CLI_SECRETS_PATH=./<path-to-secrets.txt>
./ente-cli
@@ -32,7 +33,7 @@ Then one of the following:
And you are good to go.
## References
## Ref
- [Ente CLI Secrets Path](https://www.reddit.com/r/selfhosted/comments/1gc09il/comment/lu2hox2/?utm_source=share&utm_medium=web3x&utm_name=web3xcss&utm_term=1&utm_content=share_button)
- [Keyrings](https://man7.org/linux/man-pages/man7/keyrings.7.html)

View File

@@ -1,10 +1,8 @@
---
title: General troubleshooting cases - Self-hosting
title: General troubleshooting cases
description: Fixing various errors when trying to self host Ente
---
# Troubleshooting
## Functionality not working on self hosted instance
If some specific functionality (e.g. album listing, video playback) does not

View File

@@ -1,5 +1,5 @@
---
title: Uploads - Self-hosting
title: Uploads
description: Fixing upload errors when trying to self host Ente
---
@@ -9,14 +9,23 @@ Here are some errors our community members frequently encountered with the
context and potential fixes.
Fundamentally in most situations, the problem is because of minor mistakes or
misconfiguration. Please make sure to reverse proxy Museum and MinIO API
misconfiguration. Please make sure to reverse proxy museum and MinIO API
endpoint to a domain and check your S3 credentials and whole configuration file
for any minor misconfigurations.
It is also suggested that the user setups bucket CORS or global CORS on MinIO or
any external S3 service provider they are connecting to. To setup bucket CORS,
please
[read this](/self-hosting/administration/object-storage#cors-cross-origin-resource-sharing).
please [read this](/self-hosting/troubleshooting/bucket-cors).
## What is S3 and how is it incorporated in Ente ?
S3 is an cloud storage protocol made by Amazon (specifically AWS). S3 is
designed to store files and data as objects inside buckets and it is mostly used
for online backups and storing different types of files.
Ente's Docker setup is shipped with [MinIO](https://min.io/) as its default S3
provider. MinIO supports the Amazon S3 protocol and leverages your disk storage
to dump all the uploaded files as encrypted object blobs.
## 403 Forbidden

View File

@@ -0,0 +1,14 @@
---
title: Yarn errors
description: Fixing yarn install errors when trying to self host Ente
---
# Yarn
If `yarn install` is failing, make sure you are using Yarn v1 (also known as
"Yarn Classic"):
- https://classic.yarnpkg.com/lang/en/docs/install
For more details, see the
[getting started instructions](https://github.com/ente-io/ente/blob/main/web/docs/new.md).

View File

@@ -73,7 +73,7 @@ If the code you're working needs to modify user facing strings, see
## 🔩 Architecture
The architecture that powers end-to-end encrypted storage and sync of your
tokens has been documented [here](architecture/README.md).
tokens has been documented [here](../architecture/README.md).
## 🌍 Translate

View File

@@ -10,16 +10,6 @@
{
"title": "3Commas"
},
{
"title": "Accredible",
"slug": "accredible",
"altNames": [
"Accredible Certificates",
"Accredible Badges",
"Digital Credentials",
"certificates.zaka.ai"
]
},
{
"title": "Addy.io",
"slug": "addy_io"
@@ -81,16 +71,6 @@
],
"hex": "fd4b2d"
},
{
"title": "Autenticacion Digital",
"slug": "autenticacion-digital",
"altNames": [
"autenticaciondigital.and.gov.co"
]
},
{
"title": "availity"
},
{
"title": "AzurHosts",
"slug": "azurhosts",
@@ -141,13 +121,6 @@
{
"title": "Belo"
},
{
"title": "bestbuy",
"altNames": [
"Best Buy",
"bestbuy.com"
]
},
{
"title": "Bethesda",
"altNames": [
@@ -296,13 +269,6 @@
"title": "CERN",
"slug": "cern"
},
{
"title": "Chaturbate",
"slug": "chaturbate",
"altNames": [
"Chaturbate.com"
]
},
{
"title": "ChangeNOW"
},
@@ -326,25 +292,6 @@
{
"title": "CoinDCX"
},
{
"title": "colorado",
"altNames": [
"Colorado.gov",
"Colorado Gov",
"Colorado Government",
"Colorado Government Portal",
"Colorado COVES Death Certificates",
"Colorado COVES",
"Colorado Official State Web Portal",
"Colorado State Web Portal",
"Colorado State Portal",
"Colorado Web Portal",
"Colorado Portal",
"Colorado State",
"Colorado PEAK",
"myColorado"
]
},
{
"title": "ConfigCat"
},
@@ -456,13 +403,6 @@
"Murena"
]
},
{
"title": "emeritihealth",
"altNames": [
"Emeriti Health",
"Emeriti Retirement Health"
]
},
{
"title": "eneba"
},
@@ -766,23 +706,6 @@
{
"title": "Letterboxd"
},
{
"title": "LifeMiles",
"slug": "lifemiles",
"altNames": [
"Life Miles",
"lifemiles.com",
"Avianca LifeMiles"
]
},
{
"title": "lincolnfinancial",
"altNames": [
"Lincoln Financial",
"Lincoln Financial Group",
"LFG"
]
},
{
"title": "LinkedIn",
"slug": "linkedin"
@@ -816,10 +739,6 @@
"lu.ma"
]
},
{
"title": "MangaDex",
"slug": "mangadex"
},
{
"title": "Marketplace.tf",
"slug": "marketplacedottf"
@@ -919,9 +838,6 @@
"title": "Name.com",
"slug": "name_com"
},
{
"title": "nasdaq"
},
{
"title": "Nextcloud",
"slug": "nextcloud"
@@ -1006,9 +922,6 @@
{
"title": "NuCommunity"
},
{
"title": "numerai"
},
{
"title": "NVIDIA"
},
@@ -1039,10 +952,6 @@
"title": "Oracle Cloud",
"slug": "oracle_cloud"
},
{
"title": "Pangolin",
"slug": "pangolin"
},
{
"title": "Parqet",
"slug": "parqet"
@@ -1328,19 +1237,6 @@
"PAYDAY 3"
]
},
{
"title": "Startmail",
"slug": "startmail"
},
{
"title": "Stripchat",
"slug": "stripchat",
"altNames": [
"Strip Chat",
"stripchat.com",
"StripChat Live"
]
},
{
"title": "STRATO",
"hex": "FF8800"
@@ -1359,9 +1255,6 @@
"T-Mobile ID"
]
},
{
"title": "Tableau"
},
{
"title": "TCPShield"
},
@@ -1407,10 +1300,6 @@
"title": "Termius",
"hex": "858585"
},
{
"title": "Temu",
"slug": "temu"
},
{
"title": "tianyiyun",
"altNames": [
@@ -1477,16 +1366,6 @@
"title": "Ubuntu One",
"slug": "ubuntu_one"
},
{
"title": "unitedhealthgroup",
"altNames": [
"Unitedhealth Group",
"United Healthgroup",
"UHG",
"uhg.com",
"unitedhealthgroup.com"
]
},
{
"title": "Unity",
"hex": "858585"
@@ -1571,12 +1450,6 @@
{
"title": "WYZE"
},
{
"title": "X",
"altNames": [
"Twitter"
]
},
{
"title": "Xbox",
"hex": "107C10"
@@ -1632,14 +1505,6 @@
"title": "xAI",
"slug": "xai"
},
{
"title": "XVideos",
"slug": "xvideos",
"altNames": [
"X Videos",
"xvideos.com"
]
},
{
"title": "Cronometer",
"slug": "cronometer"

View File

@@ -1,8 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<svg enable-background="new 0 0 240 240" version="1.1" viewBox="0 0 240 240" xml:space="preserve" xmlns="http://www.w3.org/2000/svg">
<path d="m1 214c0-46.021 0-92.042 0.27671-138.19 0.74988-0.75875 1.4558-1.3222 1.6616-2.0308 3.4637-11.931 9.7863-22.061 19.083-30.291 10.734-9.5027 23.139-15.388 37.612-15.425 60.455-0.15068 120.91-0.063334 181.37-0.063242 0 45.688 0 91.375-0.29245 137.19-2.9994 6.1167-5.1585 12.433-8.5123 18.034-11.681 19.506-28.965 30.541-51.873 30.666-59.773 0.32539-119.55 0.10936-179.32 0.10925m151.5-107h36.106v-14.744h-126.3v14.744h90.195m15.11 63.164c1.9138 0.27864 3.8409 0.86449 5.7391 0.78206 7.6904-0.33391 15.992-9.1312 15.551-16.275-0.4837-7.8375-8.5467-15.644-16.184-15.67-8.5565-0.02861-14.433 4.8247-16.567 13.682-1.4658 6.0848 3.2382 13.739 11.461 17.481z" fill="#5B4DFC"/>
</svg>

Before

Width:  |  Height:  |  Size: 862 B

File diff suppressed because one or more lines are too long

Before

Width:  |  Height:  |  Size: 50 KiB

File diff suppressed because one or more lines are too long

Before

Width:  |  Height:  |  Size: 15 KiB

View File

@@ -1 +0,0 @@
<svg id="Layer_1" data-name="Layer 1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 638 638"><defs><style>.cls-1{fill:#104ab8;}.cls-1,.cls-2,.cls-3,.cls-4{fill-rule:evenodd;}.cls-2{fill:#fff;}.cls-3{fill:#ffed31;}.cls-4{fill:#1c252c;}</style></defs><title>Best Buy Logo Vector</title><g id="logo-en"><polygon class="cls-1" points="0 0 638 0 638 638 0 638 0 0 0 0"/><path class="cls-2" d="M232,347.26V482.49h70.8c27.87,0,53.62-9.78,53.62-38.51,0-19.42-14-28.29-29.38-32.93,9.37-3.76,20-11.66,20-28.23,0-21.2-21-35.56-49.35-35.56Zm43.37,31.5h15.95c6.49,0,11.44,5.08,11.44,10.24,0,4.8-5.14,9.93-11.44,9.93H275.41V378.76Zm0,48.23h21c7.35,0,13.52,5.59,13.52,12,0,6.78-5.77,12.4-14.79,12.4H275.41V427Z" transform="translate(-181 -181)"/><path class="cls-2" d="M267.12,497.24V632.46h70.8c27.87,0,53.62-9.78,53.62-38.51,0-19.42-14-28.29-29.38-32.93,9.38-3.76,20-11.66,20-28.22,0-21.2-21-35.56-49.35-35.56Zm43.37,31.49h15.95c6.49,0,11.44,5.08,11.44,10.25,0,4.79-5.14,9.92-11.44,9.92H310.49V528.73Zm0,48.24h21.05c7.35,0,13.52,5.58,13.52,12,0,6.77-5.77,12.4-14.79,12.4H310.49V577Z" transform="translate(-181 -181)"/><polygon class="cls-2" points="178.87 301.47 178.87 166.25 287.94 166.25 287.94 198.9 222.11 198.9 222.11 216.64 275.56 216.64 275.56 247.25 222.11 247.25 222.11 268.94 287.94 268.94 287.94 301.47 178.87 301.47 178.87 301.47"/><path class="cls-2" d="M528,486.34c30.7,0,55.26-17.51,55.26-45.89,0-45.8-59.58-38.75-59.58-53,0-5.51,5.79-8.43,11.73-8.43,10.24,0,17.64,6.74,17.64,6.74l25.63-24.41c-10.25-9.75-26.44-18-48.26-18-32.75,0-54.19,19.45-54.19,42.9,0,46.38,58.73,39.65,58.73,54.2,0,5.11-4.91,10.24-13.81,10.24-10.11,0-18.12-6.1-24.35-11.28L471,464c10.38,10.12,27,22.32,57,22.32Z" transform="translate(-181 -181)"/><polygon class="cls-2" points="435.66 301.47 435.66 198.78 399.94 198.78 399.94 166.25 514.75 166.25 514.75 198.78 479.04 198.78 479.04 301.47 435.66 301.47 435.66 301.47"/><path class="cls-2" d="M393,497.14h43.25v81c0,8.22,8.19,15.8,16.72,15.8,8.05,0,16.19-6.84,16.19-16.23V497.14h43.12v80c0,31.76-26.36,57.09-60.45,57.09-34.28,0-58.83-27.57-58.83-58.82V497.14Z" transform="translate(-181 -181)"/><polygon class="cls-2" points="384.63 451.37 384.63 403.05 333.81 316.14 377.56 316.14 406.32 362.7 435.18 316.14 479.04 316.14 428.01 403.54 428.01 451.37 384.63 451.37 384.63 451.37"/><polygon class="cls-3" points="479.04 390.15 453.52 415.66 453.52 450.11 479.04 475.62 586.96 475.62 586.96 390.15 479.04 390.15 479.04 390.15"/><path class="cls-4" d="M655.85,613.87a5.75,5.75,0,1,1-5.75-5.74,5.74,5.74,0,0,1,5.75,5.74Z" transform="translate(-181 -181)"/></g></svg>

Before

Width:  |  Height:  |  Size: 2.5 KiB

View File

@@ -1 +0,0 @@
<svg viewBox="0 0 90 90" xmlns="http://www.w3.org/2000/svg"><defs><linearGradient x1="50%" y1="23.373%" x2="50%" y2="85.937%" id="a"><stop stop-color="#02729D" offset="0%"/><stop stop-color="#00333F" offset="100%"/></linearGradient><linearGradient x1="63.263%" y1="134.632%" x2="51.527%" y2="36.554%" id="b"><stop stop-color="#FFE5BE" offset="0%"/><stop stop-color="#FEBE1D" offset="58%"/><stop stop-color="#FCAE1E" offset="69%"/><stop stop-color="#F58420" offset="92%"/><stop stop-color="#F37321" offset="100%"/></linearGradient></defs><g fill="none"><path d="M46.126 61.143c-13.37 0-22.008-10.053-22.008-25.606.006-1.882.137-3.762.392-5.626C9.072 27.993 0 22.686 0 15.412c0-4.811 3.898-9.02 11.91-12.899L17.094 0l.207 5.767c.278 7.462 5.656 11.056 10.286 12.777C32.346 7.41 41.096.644 51.042.644c10.545 0 15.264 5.889 15.264 11.726 0 7.621-7.984 15.956-23.278 17.848-1.225 3.027-1.936 6.148-1.936 8.642 0 4.753 2.143 4.753 3.424 4.753 1.799 0 6.192-3.657 6.848-7.725l.507-3.168h3.209c6.214 0 10.234 3.797 10.234 9.679-.004 7.64-7.477 18.744-19.188 18.744Z" fill="url(#a)" transform="translate(6 15)"/><path d="M44.516 47.374c4.038 0 9.675-5.364 10.564-10.894 4.2 0 6.47 2.221 6.47 5.923 0 5.807-6.026 14.986-15.428 14.986-12.717 0-18.247-10.286-18.247-21.838a41.255 41.255 0 0 1 1.051-8.957c-14.435-1.162-25.17-5.53-25.17-11.17.008-2.936 2.94-6.208 9.798-9.524.33 9.29 7.185 15.101 16.308 17.252 3.372-10.23 10.894-18.747 21.18-18.747 7.632 0 11.503 3.65 11.503 7.961 0 5.922-7.243 13.162-22.063 14.32-1.88 3.872-3.154 8.35-3.154 12.167 0 4.815 1.991 8.52 7.188 8.52ZM42.03 23.98c7.402-.551 9.993-2.876 9.993-4.534 0-.94-.884-1.714-2.157-1.714-2.691 0-5.567 2.598-7.836 6.248Z" fill="url(#b)" transform="translate(6 15)"/><path d="M36.41 41.587a1.377 1.377 0 0 1 1.233 1.676 39.89 39.89 0 0 0-1.018 8.654c0 5.6 1.436 11.419 4.915 15.427-4.497-3.949-6.292-10.5-6.292-16.793a39.882 39.882 0 0 1 1.018-8.653c.023-.102.034-.207.033-.311Zm25.769 11.33c1.68.196 2.832.877 3.453 2.024a5.415 5.415 0 0 0-2.08-.648c-1.506 5.552-7.047 10.834-11.659 10.834-2.902 0-5.137-1.036-6.596-2.95 1.362 1.03 3.117 1.573 5.223 1.573 4.626 0 10.153-5.281 11.659-10.833Zm-5.134-32.135c4.33 0 7.577 1.288 9.12 3.442-1.773-1.325-4.441-2.066-7.747-2.066-10.323 0-17.026 9.198-19.872 17.793a1.377 1.377 0 0 1-1.625.91c-.359-.085-.703-.188-1.051-.281a1.362 1.362 0 0 0-.837-.37l-.618-.056c-4.293-1.395-7.799-3.586-10.312-6.41 2.898 2.657 6.77 4.637 11.449 5.748a1.377 1.377 0 0 0 1.625-.91c2.842-8.606 9.545-17.8 19.868-17.8Zm2.073 12.41a2.99 2.99 0 0 1 1.673 2.617c-.001.124-.01.247-.026.37a24.799 24.799 0 0 1-3.779 1.85c1.714-1.08 2.428-2.38 2.428-3.582 0-.436-.101-.865-.296-1.255ZM18.366 23.047c.1.65.235 1.293.404 1.928-4.053 2.35-6.248 4.723-6.248 6.81a3.83 3.83 0 0 0 .877 2.329c-1.458-1.162-2.258-2.414-2.258-3.702 0-2.25 2.547-4.834 7.225-7.365Z" fill-opacity=".4" fill="#FFF"/></g></svg>

Before

Width:  |  Height:  |  Size: 2.8 KiB

View File

@@ -1,16 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<svg version="1.1" xmlns="http://www.w3.org/2000/svg" width="254" height="197">
<path d="M0 0 C83.82 0 167.64 0 254 0 C254 65.01 254 130.02 254 197 C170.18 197 86.36 197 0 197 C0 131.99 0 66.98 0 0 Z " fill="#255E39" transform="translate(0,0)"/>
<path d="M0 0 C83.82 0 167.64 0 254 0 C254 20.13 254 40.26 254 61 C252 58 252 58 250.44140625 55.1015625 C245.56357778 46.07605867 239.90237971 38.57068879 233 31 C232.40574219 30.32324219 231.81148437 29.64648438 231.19921875 28.94921875 C220.24437377 17.12451014 203.62450839 8.5338504 188 5 C186.79472656 4.72285156 185.58945313 4.44570312 184.34765625 4.16015625 C158.77417322 -1.25753788 132.93293113 2.2138374 110.6875 16.3125 C104.6016815 20.31637252 99.20467262 24.91572017 94 30 C92.94425781 31.01513672 92.94425781 31.01513672 91.8671875 32.05078125 C88.51106627 35.20766805 88.51106627 35.20766805 86 39 C81.91471475 37.63823825 81.46098573 35.78559446 79.3828125 32.05859375 C79.04377899 31.45749283 78.70474548 30.85639191 78.35543823 30.23707581 C77.26990008 28.30862811 76.19708095 26.37345578 75.125 24.4375 C73.71411291 21.91357977 72.29846937 19.39234086 70.8828125 16.87109375 C70.54493713 16.26711761 70.20706177 15.66314148 69.85894775 15.04086304 C67.36815994 10.6040756 64.75182831 6.27882324 62 2 C59.33448576 4.40817141 57.69828306 6.99238148 55.91796875 10.1015625 C55.32242188 11.13708252 54.726875 12.17260254 54.11328125 13.23950195 C53.47777344 14.35671631 52.84226563 15.47393066 52.1875 16.625 C51.52109934 17.78945891 50.85442872 18.95376337 50.1875 20.11791992 C40.93068749 36.30218373 31.75265124 52.53667981 23 69 C27.95 68.01 32.9 67.02 38 66 C35.92604704 72.67301098 33.33060795 78.79820286 30.25 85.0625 C29.27859712 87.06444928 28.30863363 89.06709742 27.33984375 91.0703125 C26.54876221 92.70468262 26.54876221 92.70468262 25.74169922 94.37207031 C22.3730026 101.36581172 19.10119743 108.40590787 15.8125 115.4375 C15.13382358 116.88746733 14.45511339 118.33741885 13.77636719 119.78735352 C12.18329197 123.1911238 10.59131013 126.59540409 9 130 C12.34653694 130 15.42039041 128.66450025 18.58984375 127.65625 C21 127 21 127 24 127 C22.01427175 133.18398243 19.7878242 139.22422353 17.34765625 145.2421875 C17.00625107 146.09120636 16.66484589 146.94022522 16.31309509 147.81497192 C15.23207037 150.50266587 14.14761226 153.188954 13.0625 155.875 C6.77912222 171.34098251 6.77912222 171.34098251 1 187 C2.11632812 186.61328125 3.23265625 186.2265625 4.3828125 185.828125 C33.68892175 175.93751189 66.60784235 172.70374295 97 180 C97.66676758 180.1551709 98.33353516 180.3103418 99.02050781 180.47021484 C108.69943089 182.7670275 118.15151684 185.81999107 127.46875 189.29296875 C128.6546875 189.73253906 129.840625 190.17210937 131.0625 190.625 C132.12597656 191.02976563 133.18945312 191.43453125 134.28515625 191.8515625 C143.57746226 194.72426278 152.62428287 195.36040388 162.3125 195.3125 C164.10361206 195.30404053 164.10361206 195.30404053 165.9309082 195.29541016 C174.3610904 195.1791794 181.93838254 194.62771049 190 192 C190.93513428 191.70198486 190.93513428 191.70198486 191.88916016 191.39794922 C217.24006336 183.15751684 235.08132548 168.03878987 248.72729492 145.21801758 C251.80476766 140.09761617 251.80476766 140.09761617 254 139 C254 158.14 254 177.28 254 197 C170.18 197 86.36 197 0 197 C0 131.99 0 66.98 0 0 Z " fill="#FDFDFD" transform="translate(0,0)"/>
<path d="M0 0 C0.65613281 0.47308594 1.31226563 0.94617187 1.98828125 1.43359375 C8.19172898 6.28906392 12.5611382 12.98165036 16 20 C24.23839404 17.77769262 32.0090674 14.65817187 39.875 11.375 C42.26721473 10.38036914 44.66040281 9.38807517 47.0546875 8.3984375 C48.10124512 7.96192871 49.14780273 7.52541992 50.22607422 7.07568359 C53 6 53 6 57 5 C57 30.41 57 55.82 57 82 C56.01 82.495 56.01 82.495 55 83 C55 81.35 55 79.7 55 78 C51.21452654 76.50479006 47.4282773 75.01156244 43.64135742 73.52001953 C42.35827504 73.01435393 41.0753909 72.50818496 39.79272461 72.00146484 C31.90172043 68.88456448 23.99310874 65.84575736 16 63 C15.525625 64.093125 15.05125 65.18625 14.5625 66.3125 C8.10206161 78.96512328 -2.35460415 87.70575421 -15.4375 93 C-29.87838266 97.0535811 -45.55564041 96.50754481 -58.859375 89.4921875 C-73.15897526 80.99933099 -81.70929125 69.15197361 -86.08203125 53.2265625 C-88.73289686 42.16808167 -87.6277083 31.38695655 -83 21 C-82.39865234 19.61554688 -82.39865234 19.61554688 -81.78515625 18.203125 C-75.22740726 4.7454836 -63.31358344 -4.70987829 -49.4375 -9.9375 C-32.12753124 -14.39739533 -14.1778871 -10.52355405 0 0 Z " fill="#FBFAFA" transform="translate(197,57)"/>
<path d="M0 0 C4.17781518 3.50676714 8.11713034 7.1703933 12 11 C12.80566406 11.79277344 13.61132812 12.58554687 14.44140625 13.40234375 C22.19006532 21.50137697 28.59401999 31.29414841 32 42 C31.29689697 42.29277832 30.59379395 42.58555664 29.86938477 42.88720703 C28.88252686 43.29825684 27.89566895 43.70930664 26.87890625 44.1328125 C25.7820752 44.58946289 24.68524414 45.04611328 23.55517578 45.51660156 C21.21112215 46.49465882 18.86831579 47.47571148 16.52685547 48.45996094 C13.00083028 49.94082264 9.46957562 51.40863582 5.9375 52.875 C4.72900391 53.38546875 3.52050781 53.8959375 2.27539062 54.421875 C1.12103516 54.89882812 -0.03332031 55.37578125 -1.22265625 55.8671875 C-2.26172119 56.30144043 -3.30078613 56.73569336 -4.37133789 57.18310547 C-7 58 -7 58 -10 57 C-11.4296875 54.92578125 -11.4296875 54.92578125 -12.875 52.3125 C-19.42601148 40.51709955 -29.84217649 32.8446492 -42.5625 28.65625 C-56.42990775 24.92271714 -71.13091577 25.7886915 -83.85546875 32.5078125 C-97.34889321 40.51080907 -106.24401068 52.0414341 -110.5546875 67.203125 C-111.02309404 70.14504676 -111.01460289 72.9684764 -110.99194336 75.94140625 C-111.02545456 84.76399115 -111.02545456 84.76399115 -114.08203125 88.640625 C-116.9592845 90.92925563 -119.95266091 92.94464306 -123 95 C-125.07005107 96.76090923 -127.03276148 98.62570442 -129 100.5 C-143.70570026 114.18796331 -143.70570026 114.18796331 -150 117 C-159.57148912 93.63001896 -160.76344158 66.4060235 -151.12304688 42.85791016 C-141.87944936 21.5593662 -127.22320872 4.39468338 -107 -7 C-106.02675781 -7.56203125 -105.05351563 -8.1240625 -104.05078125 -8.703125 C-71.86898073 -26.08920004 -28.99166492 -22.13908958 0 0 Z " fill="#C30230" transform="translate(222,20)"/>
<path d="M0 0 C4.45538794 1.64894619 8.90185574 3.3200767 13.34472656 5.00244141 C15.22690683 5.70955694 17.1119842 6.40898279 18.99902344 7.10302734 C22.15076109 8.26257362 25.29431886 9.44248243 28.4375 10.625 C29.46238525 10.99681396 30.48727051 11.36862793 31.54321289 11.75170898 C32.97395142 12.29613647 32.97395142 12.29613647 34.43359375 12.8515625 C35.71834595 13.32843506 35.71834595 13.32843506 37.02905273 13.81494141 C39 15 39 15 39.84375 16.9699707 C40.49342913 25.41072381 30.94776473 35.75864029 26 42 C25.40703125 42.75925781 24.8140625 43.51851562 24.203125 44.30078125 C9.68750758 61.76294494 -14.28234764 74.8665569 -37 77 C-61.22105191 78.03276946 -85.35950409 76.70549321 -105 61 C-105.74378906 60.44441406 -106.48757812 59.88882813 -107.25390625 59.31640625 C-123.79829816 46.85775982 -123.79829816 46.85775982 -126 40 C-125.10539062 39.23816406 -124.21078125 38.47632813 -123.2890625 37.69140625 C-116.87637214 32.21935059 -110.50956553 26.71190714 -104.265625 21.046875 C-100.88076288 17.98882715 -97.44363278 14.99153574 -94 12 C-90.74459922 13.40639025 -88.85406513 15.05982643 -86.5 17.6875 C-77.43916873 26.95043159 -66.1810049 31.99274637 -53.34033203 32.2980957 C-46.39490631 32.33973156 -39.63170864 32.26258295 -33 30 C-32.21882813 29.75507813 -31.43765625 29.51015625 -30.6328125 29.2578125 C-17.23315198 24.54079805 -7.75035638 15.14019465 -1.25 2.6328125 C-0.8375 1.76398438 -0.425 0.89515625 0 0 Z " fill="#021A71" transform="translate(213,119)"/>
<path d="M0 0 C5.35552828 3.39157167 9.73048255 7.37353935 14.31640625 11.7578125 C16.86387172 13.88626254 18.8665855 14.9914145 22 16 C22.95261719 15.09636719 23.90523437 14.19273438 24.88671875 13.26171875 C26.15342443 12.07007711 27.42036387 10.87868391 28.6875 9.6875 C29.31333984 9.09259766 29.93917969 8.49769531 30.58398438 7.88476562 C33.87475275 4.80074709 36.98137595 2.12841083 41 0 C41.66644531 0.61746094 42.33289063 1.23492187 43.01953125 1.87109375 C48.7281423 7.11662866 54.5269502 12.15258764 60.58984375 16.9921875 C66.81970816 22.18205834 66.81970816 22.18205834 67.53125 25.41015625 C67.38452482 37.86345569 62.48204938 48.68984739 54.2265625 58 C46.31381371 65.47871616 35.90872336 71.06835437 25 72 C24.06671875 72.08121094 23.1334375 72.16242188 22.171875 72.24609375 C8.50219507 72.83653804 -2.2982359 67.43653936 -13.1875 59.75 C-21.40487698 51.71523139 -27.73929647 40.75799942 -28.75 29.125 C-28.43874508 24.7355076 -26.48070743 22.6315565 -23.25 19.8046875 C-22.5075 19.20914063 -21.765 18.61359375 -21 18 C-20.154375 17.30132812 -19.30875 16.60265625 -18.4375 15.8828125 C-16.58822798 14.36451814 -14.73128441 12.85552457 -12.8671875 11.35546875 C-8.44244171 7.72042555 -4.21848422 3.87075667 0 0 Z " fill="#031A71" transform="translate(144,75)"/>
<path d="M0 0 C0.89460938 0.43441406 1.78921875 0.86882813 2.7109375 1.31640625 C13.56733148 7.178859 20.58301944 16.62066024 25 28 C26.34950368 32.74608059 27 37.065874 27 42 C23.55220914 40.49993609 21.17639467 38.49590738 18.4375 35.9375 C12.27265981 30.28487205 5.96967741 24.64645161 -1 20 C-1.6290625 20.56847656 -2.258125 21.13695313 -2.90625 21.72265625 C-8.23211968 26.5271682 -13.58511587 31.29600848 -19 36 C-23.98743064 34.50843196 -26.93142754 31.54332502 -30.5625 28 C-35.25906082 23.26431569 -35.25906082 23.26431569 -41 20 C-41.66644531 20.61746094 -42.33289063 21.23492187 -43.01953125 21.87109375 C-49.49783882 27.82388826 -56.14900967 33.47570939 -63 39 C-65.00712736 40.65839866 -67.00426503 42.32789773 -69 44 C-69.89444705 31.15474652 -65.74873183 21.17814981 -58 11 C-42.95796817 -5.60359869 -19.74821462 -9.8220012 0 0 Z " fill="#FDD204" transform="translate(185,56)"/>
<path d="M0 0 C4.28792054 2.72349458 7.96086865 5.64265272 11.6875 9.125 C14.40593357 11.65919672 16.90611339 13.93740893 20 16 C18.45427224 19.81628832 16.11228755 21.97025743 13.0625 24.6875 C12.57450928 25.12392822 12.08651855 25.56035645 11.58374023 26.01000977 C7.44438884 29.68168288 3.1542964 33.15674428 -1.15625 36.625 C-4.88158413 39.73626806 -8.42845194 43.02239671 -11.94116211 46.37084961 C-14.47323772 48.75074994 -16.77334734 50.66509642 -20 52 C-20.96345444 50.12762629 -21.92053102 48.2519701 -22.875 46.375 C-23.40867187 45.33085938 -23.94234375 44.28671875 -24.4921875 43.2109375 C-27.26231047 37.31186734 -29.44678461 31.53349556 -28 25 C-26.12378629 22.11112789 -23.67216304 20.14329744 -21 18 C-20.154375 17.30132812 -19.30875 16.60265625 -18.4375 15.8828125 C-16.58822798 14.36451814 -14.73128441 12.85552457 -12.8671875 11.35546875 C-8.44244171 7.72042555 -4.21848422 3.87075667 0 0 Z " fill="#7A853B" transform="translate(144,75)"/>
<path d="M0 0 C0.30292969 1.05058594 0.60585937 2.10117188 0.91796875 3.18359375 C3.21554955 10.95006406 5.53141385 18.15450633 10 25 C9.34515625 25.52207031 8.6903125 26.04414063 8.015625 26.58203125 C2.85533541 30.74379023 -2.14926847 34.98462376 -7 39.5 C-12.46969905 44.59155144 -18.15506859 49.34016295 -24 54 C-27.98232778 50.33096724 -30.64316353 46.66489768 -33.25 41.9375 C-33.600625 41.32583984 -33.95125 40.71417969 -34.3125 40.08398438 C-35.98121521 37.11559674 -37.4271484 34.37813958 -38 31 C-31.44231174 24.87720206 -24.8192745 18.95918641 -17.8125 13.34765625 C-14.05017212 10.20715756 -10.48696844 6.86610283 -6.97070312 3.453125 C-3.32463848 0 -3.32463848 0 0 0 Z " fill="#6D3C5E" transform="translate(111,106)"/>
<path d="M0 0 C5.83043424 4.10970437 11.09789229 8.68615219 16.30078125 13.5625 C18.89058893 15.98553895 18.89058893 15.98553895 21.48046875 17.8125 C24.59352223 20.10458893 26.65980595 21.65401484 27.62890625 25.48828125 C28.05445689 35.19358123 24.02478887 43.92444646 19 52 C18.071875 51.0409375 18.071875 51.0409375 17.125 50.0625 C11.25501774 44.20900645 5.00673282 38.77135771 -1.4375 33.5625 C-7.88257776 28.34767925 -14.13523865 22.86476135 -20 17 C-19.31035156 16.443125 -18.62070313 15.88625 -17.91015625 15.3125 C-11.80242122 10.35258349 -5.83030237 5.28326166 0 0 Z " fill="#35647D" transform="translate(184,75)"/>
<path d="M0 0 C0.66 0.33 1.32 0.66 2 1 C-1.63 4.63 -5.26 8.26 -9 12 C-9.66 11.67 -10.32 11.34 -11 11 C-9.92173635 9.72486237 -8.83714481 8.45507431 -7.75 7.1875 C-7.14671875 6.47980469 -6.5434375 5.77210937 -5.921875 5.04296875 C-4.07629602 3.08110329 -2.20054668 1.54330375 0 0 Z " fill="#FEDE22" transform="translate(135,60)"/>
<path d="M0 0 C3.75931429 1.03381143 5.16972619 2.16972619 8 5 C4.37 4.01 0.74 3.02 -3 2 C-2.01 1.34 -1.02 0.68 0 0 Z " fill="#45755B" transform="translate(109,181)"/>
<path d="M0 0 C0.33 0.66 0.66 1.32 1 2 C6.445 1.505 6.445 1.505 12 1 C12 1.33 12 1.66 12 2 C7.71 2.66 3.42 3.32 -1 4 C-0.67 2.68 -0.34 1.36 0 0 Z " fill="#4F7F60" transform="translate(24,65)"/>
</svg>

Before

Width:  |  Height:  |  Size: 13 KiB

View File

@@ -1,11 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<svg version="1.1" xmlns="http://www.w3.org/2000/svg" width="121" height="111">
<path d="M0 0 C39.93 0 79.86 0 121 0 C121 36.63 121 73.26 121 111 C81.07 111 41.14 111 0 111 C0 74.37 0 37.74 0 0 Z " fill="#FDFDFC" transform="translate(0,0)"/>
<path d="M0 0 C1.34094727 -0.00483398 1.34094727 -0.00483398 2.70898438 -0.00976562 C15.92329958 0.09656756 29.05768111 5.15920937 38.69921875 14.3671875 C46.33623486 22.91378081 51.45414229 32.03867724 53.4375 43.3125 C55.4175 42.9825 57.3975 42.6525 59.4375 42.3125 C56.40996635 50.06943534 46.82853593 55.97682128 39.5 59.3125 C37.82136046 60.00117263 36.13406518 60.66925254 34.4375 61.3125 C33.5609375 61.67085937 32.684375 62.02921875 31.78125 62.3984375 C20.17960201 66.92308022 6.59150797 64.44771949 -4.48828125 59.66015625 C-6.56191878 58.74121933 -8.62982096 57.81032187 -10.69677734 56.87646484 C-21.71786864 51.93615813 -31.96757967 49.00024219 -43.6875 53.25 C-49.85297476 56.02724089 -53.58090596 59.9493408 -57.5625 65.3125 C-58.41134766 66.43978516 -58.41134766 66.43978516 -59.27734375 67.58984375 C-59.70144531 68.15832031 -60.12554687 68.72679688 -60.5625 69.3125 C-60.21265815 63.71503042 -56.42242893 59.17242893 -52.5625 55.3125 C-52.45417831 53.23031638 -52.37676459 51.14650871 -52.3125 49.0625 C-51.32728272 34.37380601 -44.38377625 22.27099897 -33.859375 12.1953125 C-23.67156706 3.84408218 -13.05318857 -0.23629958 0 0 Z " fill="#7D9C07" transform="translate(60.5625,2.6875)"/>
<path d="M0 0 C39.93 0 79.86 0 121 0 C121 15.18 121 30.36 121 46 C118.69 46 116.38 46 114 46 C113.72027344 45.10539062 113.44054687 44.21078125 113.15234375 43.2890625 C110.46208014 35.17501984 107.34684612 28.77440212 102 22 C101.401875 21.113125 100.80375 20.22625 100.1875 19.3125 C91.26978576 9.88520209 79.12630771 4.33913818 66.27734375 3.7265625 C48.74009638 3.25612695 36.53738751 7.13555151 23.3125 19.1875 C14.84180419 28.0987521 10.10977052 38.99431955 9.6875 51.125 C9.34944073 57.79987234 7.81473954 60.61643116 3 65 C2.01 66.32 1.02 67.64 0 69 C0 46.23 0 23.46 0 0 Z " fill="#FDFEFC" transform="translate(0,0)"/>
<path d="M0 0 C7.7514671 5.16764473 13.82626339 13.90836132 16.703125 22.71875 C16.703125 24.03875 16.703125 25.35875 16.703125 26.71875 C11.46215703 26.16706916 7.64974874 24.39540175 3.078125 21.96875 C-14.90773287 12.27142089 -14.90773287 12.27142089 -34.734375 12.4375 C-39.88111467 14.59356662 -45.70693353 17.53886707 -48.296875 22.71875 C-47.08 22.615625 -45.863125 22.5125 -44.609375 22.40625 C-34.14474874 22.43895196 -24.29281839 28.5635433 -15.1953125 33.265625 C-10.48229066 35.6284877 -6.28828923 36.00534278 -1.109375 36.28125 C0.01500977 36.34602539 0.01500977 36.34602539 1.16210938 36.41210938 C3.00890875 36.51797685 4.85599334 36.6188476 6.703125 36.71875 C3.65258646 39.76928854 0.59053342 39.47031177 -3.60205078 39.58984375 C-11.64954951 39.3417513 -18.79427187 36.1503666 -26.171875 33.21875 C-39.2911509 28.00909237 -50.24239432 25.58953741 -64.296875 28.71875 C-63.91593636 18.62387614 -58.87170481 10.32516481 -51.57421875 3.50390625 C-35.74413322 -8.9049258 -17.299832 -9.65024642 0 0 Z " fill="#FBFCF9" transform="translate(85.296875,20.28125)"/>
<path d="M0 0 C0.07476562 0.59425781 0.14953125 1.18851563 0.2265625 1.80078125 C1.89490592 12.31788733 7.03959282 21.85443765 15 29 C18.20627298 31.27541953 21.4909817 33.22982559 25 35 C26.60294922 35.81017578 26.60294922 35.81017578 28.23828125 36.63671875 C32.50890201 38.42008659 36.60502154 38.5364421 41.1875 38.5 C42.02394043 38.49427979 42.86038086 38.48855957 43.72216797 38.48266602 C54.81538411 38.16495288 64.10602396 33.8155071 72 26 C76.47244994 20.53700746 79.32082187 14.4918547 82 8 C85.96 8 89.92 8 94 8 C91.39683113 21.53647814 84.16445962 32.6524866 73.296875 41.1015625 C60.88291389 49.43665068 45.9146679 53.47483724 31.00488281 50.61767578 C22.25796227 48.44289499 14.98853845 44.65676037 8 39 C6.948125 38.236875 5.89625 37.47375 4.8125 36.6875 C-1.36142088 30.78797561 -5.25051243 24.03047722 -8.4375 16.1875 C-8.69660156 15.55344238 -8.95570312 14.91938477 -9.22265625 14.26611328 C-10.58441341 10.72610583 -11.29621798 7.7930351 -11 4 C-4.5 0 -4.5 0 0 0 Z " fill="#7D9C08" transform="translate(20,59)"/>
<path d="M0 0 C2.01050607 0.26263368 4.00961749 0.61336248 6 1 C8.78756093 1.25820896 11.57995448 1.40834288 14.375 1.5625 C15.11105469 1.60568359 15.84710938 1.64886719 16.60546875 1.69335938 C18.40348068 1.79843799 20.20171958 1.89962093 22 2 C19.47636907 4.52363093 17.87673704 4.2605272 14.4296875 4.2734375 C13.71039063 4.26570313 12.99109375 4.25796875 12.25 4.25 C11.54617187 4.25773437 10.84234375 4.26546875 10.1171875 4.2734375 C5.70222524 4.257025 2.15942781 3.64807517 -2 2 C-1.34 1.34 -0.68 0.68 0 0 Z " fill="#DFE7C3" transform="translate(70,55)"/>
<path d="M0 0 C0.99 0.33 1.98 0.66 3 1 C2.60167969 1.45890625 2.20335937 1.9178125 1.79296875 2.390625 C-0.91142062 5.52271585 -3.57991771 8.63877459 -6 12 C-5.54300722 6.97307937 -3.00758252 3.85103739 0 0 Z " fill="#9DB444" transform="translate(6,60)"/>
<path d="M0 0 C0 0.66 0 1.32 0 2 C0.66 2.33 1.32 2.66 2 3 C-4.625 2.25 -4.625 2.25 -8 0 C-5.13822943 -1.43088528 -3.06624227 -0.59991697 0 0 Z " fill="#E9EED6" transform="translate(76,56)"/>
</svg>

Before

Width:  |  Height:  |  Size: 5.1 KiB

View File

@@ -1,101 +0,0 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Generator: Adobe Illustrator 26.4.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
version="1.1"
id="Layer_1"
x="0px"
y="0px"
viewBox="0 0 1000 425.96859"
xml:space="preserve"
sodipodi:docname="lifemiles-logo-white.svg"
width="1000"
height="425.9686"
inkscape:version="0.92.4 (5da689c313, 2019-01-14)"><metadata
id="metadata39"><rdf:RDF><cc:Work
rdf:about=""><dc:format>image/svg+xml</dc:format><dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" /><dc:title></dc:title></cc:Work></rdf:RDF></metadata><defs
id="defs37">
</defs><sodipodi:namedview
pagecolor="#ffffff"
bordercolor="#111111"
borderopacity="1"
objecttolerance="10"
gridtolerance="10"
guidetolerance="10"
inkscape:pageopacity="0"
inkscape:pageshadow="2"
inkscape:window-width="1920"
inkscape:window-height="1017"
id="namedview35"
showgrid="false"
fit-margin-top="0"
fit-margin-left="0"
fit-margin-right="0"
fit-margin-bottom="0"
inkscape:zoom="0.21047873"
inkscape:cx="874.3819"
inkscape:cy="-478.96841"
inkscape:window-x="1912"
inkscape:window-y="-8"
inkscape:window-maximized="1"
inkscape:current-layer="Layer_1"><inkscape:grid
type="xygrid"
id="grid80"
originx="112"
originy="919.50723" /></sodipodi:namedview>
<style
type="text/css"
id="style2">
.st0{fill:#FFFFFF;}
</style>
<path
inkscape:connector-curvature="0"
style="fill:#2c3d47;fill-opacity:1;stroke-width:17.97037315"
id="path10"
d="m 503.10835,200.17953 c -10.36162,0 -19.4727,2.34995 -27.33325,7.23061 -7.8605,4.88066 -14.64912,10.48438 -20.18731,16.81116 1.6079,6.86908 2.67979,14.64198 3.21574,23.49947 0.53591,8.85749 0.89324,17.35347 0.89324,25.30714 v 152.56585 h -95.57696 v -154.3735 c 0,-24.58407 -3.03703,-42.47983 -9.28969,-54.0488 -6.0741,-11.38821 -16.97163,-17.17269 -32.51405,-17.17269 -10.0043,0 -18.57946,2.16919 -25.90406,6.68831 -7.32459,4.51913 -13.21998,9.94208 -17.50752,16.26887 V 425.59376 H 183.50616 V 129.6811 h 91.82531 v 39.22605 c 9.11113,-16.0881 21.08054,-27.47631 36.08706,-34.3454 14.82782,-6.86907 30.01291,-10.30361 45.55533,-10.30361 19.11543,0 34.83648,3.97684 47.34185,11.74974 12.50539,7.7729 24.29616,20.60723 35.5511,38.32222 20.7232,-33.44156 53.05854,-50.07196 97.18473,-50.07196 19.11537,0 35.19376,4.1576 48.2351,12.29204 13.04134,8.3152 23.76025,19.16112 31.79944,32.89926 8.21784,13.73816 13.93458,29.46473 17.50754,47.36049 3.573,17.89575 5.35947,36.69535 5.35947,56.39874 v 152.56589 h -95.39833 v -154.5543 c 0,-24.58407 -3.03703,-42.47983 -9.28969,-54.0488 -5.89539,-11.38821 -16.79299,-16.99193 -32.15672,-16.99193"
class="st0" /><path
inkscape:connector-curvature="0"
style="fill:#2c3d47;fill-opacity:1;stroke-width:18.07651901"
id="path12"
d="m 94.576402,332.35756 c 0,12.5291 8.918858,22.3039 25.860738,22.3039 h 65.76015 l -2.21663,70.9323 H 120.43714 C 81.005734,425.59376 0,419.93116 0,349.78556 V 0 h 94.576402 z"
class="st0"
sodipodi:nodetypes="ccccccccc" /><path
class="st0"
d="m 733.71651,296.61048 c 29.55738,-29.55737 77.63263,-29.55737 107.19006,0 29.55734,29.5574 29.55734,77.63268 0,107.19008 -29.55743,29.5574 -77.63268,29.5574 -107.19006,0 -29.55738,-29.7355 -29.55738,-77.63268 0,-107.19008"
id="path24"
style="fill:#ff1d1e;fill-opacity:1;stroke-width:17.80565071"
inkscape:connector-curvature="0" /><path
class="st0"
d="m 733.71651,22.93762 c 29.55738,-29.55739 77.63263,-29.55739 107.19006,0 29.55734,29.55739 29.55734,77.63263 0,107.19003 -29.55743,29.55737 -77.63268,29.55737 -107.19006,0 -29.55738,-29.73544 -29.55738,-77.63264 0,-107.19003"
id="path26"
style="fill:#ff1d1e;fill-opacity:1;stroke-width:17.80565071"
inkscape:connector-curvature="0" /><path
class="st0"
d="m 870.64206,159.68502 c 29.55734,-29.55737 77.63259,-29.55737 107.18993,0 29.55731,29.55739 29.55731,77.63264 0,107.19001 -29.55734,29.5574 -77.63259,29.5574 -107.18993,0 -29.73549,-29.55737 -29.73549,-77.63262 0,-107.19001"
id="path28"
style="fill:#ff1d1e;fill-opacity:1;stroke-width:17.80565071"
inkscape:connector-curvature="0" /></svg>

Before

Width:  |  Height:  |  Size: 4.5 KiB

File diff suppressed because one or more lines are too long

Before

Width:  |  Height:  |  Size: 25 KiB

File diff suppressed because one or more lines are too long

Before

Width:  |  Height:  |  Size: 5.0 KiB

View File

@@ -1,12 +0,0 @@
<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" viewBox="0 0 70.1 60" style="enable-background:new 0 0 70.1 60;" xml:space="preserve">
<style type="text/css">
.st0{fill-rule:evenodd;clip-rule:evenodd;fill:#0090BA;}
</style>
<g>
<path class="st0" d="M53.3,0L37.7,43c-0.4,1.1-1.4,1.8-2.5,2v0h16.5c1.3,0,2.4-0.8,2.8-2L70.1,0H53.3z M33.9,44.3
c1,0,1.8-0.5,2.3-1.2c0.1-0.1,0.2-0.3,0.4-0.7l5.7-15.8l-3.3-9.2c-0.4-1-1.4-1.7-2.6-1.7c-1,0-1.8,0.5-2.3,1.2
c-0.1,0.1-0.3,0.4-0.4,0.7l-5.7,15.8l3.4,9.2C31.7,43.6,32.7,44.3,33.9,44.3z M18.4,15h16.7v0c-1.2,0.1-2.3,0.9-2.7,2L16.8,60H0
l15.6-43C16,15.9,17.1,15,18.4,15z">
</path>
</g>
</svg>

Before

Width:  |  Height:  |  Size: 719 B

File diff suppressed because one or more lines are too long

Before

Width:  |  Height:  |  Size: 10 KiB

View File

@@ -1,22 +0,0 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->
<svg
width="900.82861"
height="955.20648"
viewBox="0 0 238.34422 252.7317"
version="1.1"
id="svg420"
xmlns="http://www.w3.org/2000/svg"
xmlns:svg="http://www.w3.org/2000/svg">
<defs
id="defs417" />
<g
id="layer1"
transform="translate(-13.119542,-5.9258171)">
<path
d="m 213.66176,90.072122 c 4.95655,0 8.97383,4.018046 8.97383,8.973827 0,4.956581 -4.01728,8.974621 -8.97383,8.974621 -4.95657,0 -8.97462,-4.01804 -8.97462,-8.974621 0,-4.955781 4.01805,-8.973827 8.97462,-8.973827 z m 35.2316,37.450998 c -0.90048,29.80928 -23.66033,69.21262 -54.51292,79.34466 -36.04206,11.836 -63.40991,-5.92226 -72.08409,-26.74061 -6.75754,-16.21966 -1.65117,-35.62363 10.96266,-43.83669 10.6506,-6.93533 30.48543,-8.76736 47.15454,2.19144 -5.85627,-15.34246 -21.62491,-25.4256 -35.59101,-28.49424 -13.96613,-3.06867 -28.38324,0.43858 -38.74504,5.69946 13.29071,-14.68572 44.40801,-28.946049 78.24077,-10.95958 22.67676,12.05491 32.43775,28.93208 42.0489,51.72763 C 251.59637,117.87858 234.026,71.411066 203.39074,43.794029 172.15544,15.636686 129.95516,4.340214 97.668803,6.103155 108.32483,12.678273 120.84625,22.06586 132.41209,33.053363 81.298533,26.697169 39.174705,38.314245 13.119542,73.749217 27.67508,70.878527 46.868833,69.073666 65.974711,70.016861 28.737658,96.252107 7.1124298,140.38147 18.105298,186.43137 c 6.718497,-11.74129 16.767711,-25.84558 28.726275,-38.62863 -3.677175,34.36994 1.42836,80.83745 45.62293,110.85478 -2.25587,-9.42394 -4.08014,-20.88443 -4.91466,-33.0154 20.673197,16.1282 50.685067,29.42205 87.917917,20.24096 65.77679,-16.21975 83.34719,-79.78335 73.4356,-118.35996"
style="fill:#f36118;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0.0776283"
id="path32" />
</g>
</svg>

Before

Width:  |  Height:  |  Size: 1.8 KiB

View File

@@ -1,15 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Generator: Adobe Illustrator 27.0.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
<svg version="1.1" id="Слой_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
width="500px" height="500px" viewBox="0 0 500 500" style="enable-background:new 0 0 500 500;" xml:space="preserve">
<style type="text/css">
.st0{fill:#6573FF;}
.st1{fill:#202945;}
</style>
<g>
<path class="st0" d="M500,47.2C500,20.9,478.6,0,452.9,0H47.7C21.4-0.5,0,20.9,0,47.2v43.9c0,0,186.4,180.6,250.5,180.6
C319.6,271.7,500,92.2,500,92.2S500,56.5,500,47.2z"/>
<path class="st1" d="M0,452.8C0,479.1,21.4,500,47.2,500h405.6c26.3,0,47.2-21.4,47.2-47.2V142.7c0,0-159.2,184.4-249.7,184.4
C160.8,327.1,0,178.4,0,178.4C0,236.6,0,395.2,0,452.8z"/>
</g>
</svg>

Before

Width:  |  Height:  |  Size: 843 B

View File

@@ -1 +0,0 @@
<svg viewBox="0 0 90 90" xmlns="http://www.w3.org/2000/svg"><path d="M44.86 8.486c23.44 0 42.423 15.87 42.423 35.463 0 18.47-16.877 33.633-38.366 35.318-.749.072-1.57-.61-1.57-1.406V57c0-1.032.538-1.853 1.31-2.602l15.893-17.04c1.172-1.267.26-2.275-.513-2.275H24.893c-.749 0-1.901 1.008-.47 2.506l15.892 16.78c.773.773 1.032 1.546 1.032 2.602v20.602c0 .797-.869 1.641-1.545 1.57a32.528 32.528 0 0 1-3.399-.447c-10.08-1.709-2.673 2.414-28.968 7.22 6.048-11.343 10.455-13.969 5.626-18.514A32.292 32.292 0 0 1 2.49 43.915c0-19.593 18.984-35.462 42.375-35.462v.033h-.005Z" fill="#A02831"/></svg>

Before

Width:  |  Height:  |  Size: 590 B

View File

@@ -1,52 +0,0 @@
<svg version="1.1" id="Layer_1" xmlns:x="ns_extend;" xmlns:i="ns_ai;" xmlns:graph="ns_graphs;" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" viewBox="0 0 100.2 98" style="enable-background:new 0 0 100.2 98;" xml:space="preserve">
<style type="text/css">
.st0{fill:#E8762C;}
.st1{fill:#C72035;}
.st2{fill:#59879B;}
.st3{fill:#5B6591;}
.st4{fill:#EB912C;}
.st5{fill:#1F447E;}
.st6{fill:#7099A6;}
</style>
<metadata>
<sfw xmlns="ns_sfw;">
<slices>
</slices>
<sliceSourceBounds bottomLeftOrigin="true" height="98" width="100.2" x="-301.9" y="-233.3">
</sliceSourceBounds>
</sfw>
</metadata>
<g>
<g>
<g id="icon_1_">
<polygon class="st0" points="65.7,51.8 52,51.8 52,66.8 46.6,66.8 46.6,51.8 32.8,51.8 32.8,46.6 46.6,46.6 46.6,31.6 52,31.6
52,46.6 65.7,46.6 ">
</polygon>
<polygon class="st1" points="38.2,70.3 25.9,70.3 25.9,56.8 21.3,56.8 21.3,70.3 8.8,70.3 8.8,74.3 21.3,74.3 21.3,87.6
25.9,87.6 25.9,74.3 38.2,74.3 ">
</polygon>
<polygon class="st2" points="90.7,23 78.3,23 78.3,9.6 73.7,9.6 73.7,23 61.4,23 61.4,27.2 73.7,27.2 73.7,40.5 78.3,40.5
78.3,27.2 90.7,27.2 ">
</polygon>
<polygon class="st3" points="59.8,84.9 51.5,84.9 51.5,75.6 47.5,75.6 47.5,84.9 39,84.9 39,88.5 47.5,88.5 47.5,98 51.5,98
51.5,88.5 59.8,88.5 ">
</polygon>
<polygon class="st4" points="38.1,22.9 25.6,22.9 25.6,9.6 21.1,9.6 21.1,22.9 8.6,22.9 8.6,26.9 21.1,26.9 21.1,40.5 25.6,40.5
25.6,26.9 38.1,26.9 ">
</polygon>
<polygon class="st3" points="100.2,47.4 91.9,47.4 91.9,38.1 87.8,38.1 87.8,47.4 79.4,47.4 79.4,51 87.8,51 87.8,60.3
91.9,60.3 91.9,51 100.2,51 ">
</polygon>
<polygon class="st5" points="89.9,70.3 77.6,70.3 77.6,56.8 73,56.8 73,70.3 60.6,70.3 60.6,74.3 73,74.3 73,87.6 77.6,87.6
77.6,74.3 89.9,74.3 ">
</polygon>
<polygon class="st6" points="59.2,9.3 50.9,9.3 50.9,0 47.9,0 47.9,9.3 39.6,9.3 39.6,12.1 47.9,12.1 47.9,21.2 50.9,21.2
50.9,12.1 59.2,12.1 ">
</polygon>
<polygon class="st6" points="19.6,47.8 11.3,47.8 11.3,38.7 8.3,38.7 8.3,47.8 0,47.8 0,50.6 8.3,50.6 8.3,59.7 11.3,59.7
11.3,50.6 19.6,50.6 ">
</polygon>
</g>
</g>
</g>
</svg>

Before

Width:  |  Height:  |  Size: 2.2 KiB

File diff suppressed because one or more lines are too long

Before

Width:  |  Height:  |  Size: 5.3 KiB

File diff suppressed because one or more lines are too long

Before

Width:  |  Height:  |  Size: 8.7 KiB

View File

@@ -1,18 +0,0 @@
<svg version="1.1" id="Layer_1" xmlns:x="ns_extend;" xmlns:i="ns_ai;" xmlns:graph="ns_graphs;" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" viewBox="0 0 49.8 45" style="enable-background:new 0 0 49.8 45;" xml:space="preserve">
<style type="text/css">
.st0{fill:#FFFFFF;}
</style>
<metadata>
<sfw xmlns="ns_sfw;">
<slices>
</slices>
<sliceSourceBounds bottomLeftOrigin="true" height="45" width="49.8" x="-67.2" y="-209.8">
</sliceSourceBounds>
</sfw>
</metadata>
<g>
<path class="st0" d="M39.2,0h7.6L30.2,19.1L49.8,45H34.4l-12-15.7L8.6,45H1l17.8-20.4L0,0h15.8l10.9,14.4L39.2,0z M36.5,40.4h4.2
L13.5,4.3H8.9L36.5,40.4z">
</path>
</g>
</svg>

Before

Width:  |  Height:  |  Size: 717 B

View File

@@ -1 +0,0 @@
<svg viewBox="0 0 90 90" xmlns="http://www.w3.org/2000/svg"><g fill="none" fill-rule="evenodd"><path fill="#000" d="M0 0h90v90H0z"/><path d="m32 11 13 19.217L58 11h17L53.5 42.783 78 79H61L45 55.348 29 79H12l24.5-36.217L15 11h17Z" fill="#F40000"/></g></svg>

Before

Width:  |  Height:  |  Size: 256 B

View File

@@ -232,44 +232,44 @@ EXTERNAL SOURCES:
:path: ".symlinks/plugins/url_launcher_ios/ios"
SPEC CHECKSUMS:
app_links: e7a6750a915a9e161c58d91bc610e8cd1d4d0ad0
connectivity_plus: ddd7f30999e1faaef5967c23d5b6d503d10434db
cupertino_http: 947a233f40cfea55167a49f2facc18434ea117ba
device_info_plus: c6fb39579d0f423935b0c9ce7ee2f44b71b9fce6
app_links: 3da4c36b46cac3bf24eb897f1a6ce80bda109874
connectivity_plus: 3f6c9057f4cd64198dc826edfb0542892f825343
cupertino_http: 94ac07f5ff090b8effa6c5e2c47871d48ab7c86c
device_info_plus: 335f3ce08d2e174b9fdc3db3db0f4e3b1f66bd89
DKImagePickerController: 946cec48c7873164274ecc4624d19e3da4c1ef3c
DKPhotoGallery: b3834fecb755ee09a593d7c9e389d8b5d6deed60
file_picker: 09aa5ec1ab24135ccd7a1621c46c84134bfd6655
file_saver: 503e386464dbe118f630e17b4c2e1190fa0cf808
fk_user_agent: 1f47ec39291e8372b1d692b50084b0d54103c545
file_picker: 9b3292d7c8bc68c8a7bf8eb78f730e49c8efc517
file_saver: 6cdbcddd690cb02b0c1a0c225b37cd805c2bf8b6
fk_user_agent: 137145b086229251761678fe034da53753f4ce59
Flutter: e0871f40cf51350855a761d2e70bf5af5b9b5de7
flutter_email_sender: 10a22605f92809a11ef52b2f412db806c6082d40
flutter_inappwebview_ios: 6f63631e2c62a7c350263b13fa5427aedefe81d4
flutter_local_authentication: 1172a4dd88f6306dadce067454e2c4caf07977bb
flutter_local_notifications: 4cde75091f6327eb8517fa068a0a5950212d2086
flutter_native_splash: edf599c81f74d093a4daf8e17bd7a018854bc778
flutter_secure_storage: d33dac7ae2ea08509be337e775f6b59f1ff45f12
fluttertoast: e9a18c7be5413da53898f660530c56f35edfba9c
local_auth_darwin: 66e40372f1c29f383a314c738c7446e2f7fdadc3
move_to_background: 39a5b79b26d577b0372cbe8a8c55e7aa9fcd3a2d
flutter_email_sender: 2397f5e84aaacfb61af569637a963e7c687858d8
flutter_inappwebview_ios: b89ba3482b96fb25e00c967aae065701b66e9b99
flutter_local_authentication: 989278c681612f1ee0e36019e149137f114b9d7f
flutter_local_notifications: ad39620c743ea4c15127860f4b5641649a988100
flutter_native_splash: 35ddbc7228eafcb3969dcc5f1fbbe27c1145a4f0
flutter_secure_storage: 1ed9476fba7e7a782b22888f956cce43e2c62f13
fluttertoast: 76fea30fcf04176325f6864c87306927bd7d2038
local_auth_darwin: 553ce4f9b16d3fdfeafce9cf042e7c9f77c1c391
move_to_background: 155f7bfbd34d43ad847cb630d2d2d87c17199710
MTBBarcodeScanner: f453b33c4b7dfe545d8c6484ed744d55671788cb
objective_c: 77e887b5ba1827970907e10e832eec1683f3431d
objective_c: 89e720c30d716b036faf9c9684022048eee1eee2
OrderedSet: e539b66b644ff081c73a262d24ad552a69be3a94
package_info_plus: 58f0028419748fad15bf008b270aaa8e54380b1c
path_provider_foundation: 2b6b4c569c0fb62ec74538f866245ac84301af46
privacy_screen: 1a131c052ceb3c3659934b003b0d397c2381a24e
qr_code_scanner: bb67d64904c3b9658ada8c402e8b4d406d5d796e
package_info_plus: 580e9a5f1b6ca5594e7c9ed5f92d1dfb2a66b5e1
path_provider_foundation: 080d55be775b7414fd5a5ef3ac137b97b097e564
privacy_screen: 3159a541f5d3a31bea916cfd4e58f9dc722b3fd4
qr_code_scanner: d77f94ecc9abf96d9b9b8fc04ef13f611e5a147a
SDWebImage: f84b0feeb08d2d11e6a9b843cb06d75ebf5b8868
Sentry: da60d980b197a46db0b35ea12cb8f39af48d8854
sentry_flutter: 2df8b0aab7e4aba81261c230cbea31c82a62dd1b
share_plus: 8875f4f2500512ea181eef553c3e27dba5135aad
shared_preferences_foundation: fcdcbc04712aee1108ac7fda236f363274528f78
sodium_libs: 1faae17af662384acbd13e41867a0008cd2e2318
sqflite: 673a0e54cc04b7d6dba8d24fb8095b31c3a99eec
sentry_flutter: 27892878729f42701297c628eb90e7c6529f3684
share_plus: 011d6fb4f9d2576b83179a3a5c5e323202cdabcf
shared_preferences_foundation: 9e1978ff2562383bd5676f64ec4e9aa8fa06a6f7
sodium_libs: 6c6d0e83f4ee427c6464caa1f1bdc2abf3ca0b7f
sqflite: c35dad70033b8862124f8337cc994a809fcd9fa3
sqlite3: 0bb0e6389d824e40296f531b858a2a0b71c0d2fb
sqlite3_flutter_libs: c00457ebd31e59fa6bb830380ddba24d44fbcd3b
sqlite3_flutter_libs: 9379996d65aa23dcda7585a5b58766cebe0aa042
SwiftyGif: 706c60cf65fa2bc5ee0313beece843c8eb8194d4
Toast: 1f5ea13423a1e6674c4abdac5be53587ae481c4e
url_launcher_ios: 5334b05cef931de560670eeae103fd3e431ac3fe
url_launcher_ios: 694010445543906933d732453a59da0a173ae33d
PODFILE CHECKSUM: 78f002751f1a8f65042b8da97902ba4124271c5a

View File

@@ -78,7 +78,6 @@
"contactSupport": "Звярнуцца ў службу падтрымкі",
"rateUsOnStore": "Ацаніць нас у {storeName}",
"blog": "Блог",
"merchandise": "Тавары",
"verifyPassword": "Праверыць пароль",
"pleaseWait": "Пачакайце...",
"generatingEncryptionKeysTitle": "Генерацыя ключоў шыфравання...",
@@ -86,9 +85,6 @@
"useRecoveryKey": "Выкарыстоўваць ключ аднаўлення",
"incorrectPasswordTitle": "Няправільны пароль",
"welcomeBack": "З вяртаннем!",
"emailAlreadyRegistered": "Электронная пошта ўжо зарэгістравана.",
"emailNotRegistered": "Электронная пошта не зарэгістравана.",
"madeWithLoveAtPrefix": "зроблена з ❤️ у ",
"changeEmail": "Змяніць адрас электроннай пошты",
"changePassword": "Змяніць пароль",
"data": "Даныя",
@@ -98,13 +94,9 @@
"passwordForDecryptingExport": "Пароль для дэшыфроўкі экспартавання",
"passwordEmptyError": "Пароль не можа быць пустым",
"importFromApp": "Імпартаваць коды з {appName}",
"importSelectJsonFile": "Выбраць файл JSON",
"importSelectAppExport": "Выберыце файл экспартавання {appName}",
"exportCodes": "Экспартаваць коды",
"importLabel": "Імпарт",
"selectFile": "Выбраць файл",
"emailVerificationToggle": "Праверка эл. пошты",
"authenticateGeneric": "Прайдзіце аўтэнтыфікацыю",
"ok": "OK",
"cancel": "Скасаваць",
"yes": "Так",
@@ -121,29 +113,19 @@
"enterYourPasswordHint": "Увядзіце ваш пароль",
"forgotPassword": "Забылі пароль",
"oops": "Вой",
"suggestFeatures": "Прапанаваць функцыю",
"faq": "Частыя пытанні",
"leaveFamily": "Пакінуць сямейны план",
"inFamilyPlanMessage": "Вы ўдзельнік сямейнага плана!",
"scan": "Сканіраваць",
"scanACode": "Сканіраваць код",
"verify": "Праверыць",
"verifyEmail": "Праверыць электронную пошту",
"lostDeviceTitle": "Згубілі прыладу?",
"twoFactorAuthTitle": "Двухфактарная аўтэнтыфікацыя",
"passkeyAuthTitle": "Праверка ключа доступу",
"verifyPasskey": "Праверыць ключ доступу",
"loginWithTOTP": "Увайсці з TOTP",
"recoverAccount": "Аднавіць уліковы запіс",
"enterRecoveryKeyHint": "Увядзіце свой ключ аднаўлення",
"recover": "Аднавіць",
"invalidQRCode": "Памылковы QR-код",
"noRecoveryKeyTitle": "Няма ключа аднаўлення?",
"enterEmailHint": "Увядзіце свой адрас электроннай пошты",
"enterNewEmailHint": "Увядзіце свой новы адрас электроннай пошты",
"invalidEmailTitle": "Памылковы адрас электроннай пошты",
"deleteAccount": "Выдаліць уліковы запіс",
"yesSendFeedbackAction": "Так. Адправіць водгук",
"noDeleteAccountAction": "Не, выдаліць уліковы запіс",
"sendEmail": "Адправіць ліст",
"createNewAccount": "Стварыць новы ўліковы запіс",
@@ -158,21 +140,16 @@
"social": "Сацыяльныя сеткі",
"security": "Бяспека",
"lockscreen": "Экран блакіроўкі",
"viewActiveSessions": "Паглядзець актыўныя сеансы",
"searchHint": "Пошук...",
"search": "Пошук",
"noResult": "Няма вынікаў",
"addCode": "Дадаць код",
"scanAQrCode": "Сканіраваць QR-код",
"enterDetailsManually": "Увесці падрабязнасці ўручную",
"edit": "Рэдагаваць",
"share": "Абагуліць",
"shareCodes": "Абагуліць коды",
"restore": "Аднавіць",
"copiedToClipboard": "Скапіявана ў буфер абмену",
"copiedNextToClipboard": "Скапіяваць наступны код у буфер абмену",
"error": "Памылка",
"recoveryKeyCopiedToClipboard": "Ключ аднаўлення скапіяваны ў буфер абмену",
"doThisLater": "Зрабіць гэта пазней",
"saveKey": "Захаваць ключ",
"save": "Захаваць",
@@ -187,118 +164,57 @@
"changePasswordTitle": "Змяніць пароль",
"resetPasswordTitle": "Скінуць пароль",
"encryptionKeys": "Ключы шыфравання",
"passwordChangedSuccessfully": "Пароль паспяхова зменены",
"generatingEncryptionKeys": "Генерацыя ключоў шыфравання...",
"continueLabel": "Працягнуць",
"insecureDevice": "Небяспечная прылада",
"howItWorks": "Як гэта працуе",
"logInLabel": "Увайсці",
"logout": "Выйсці",
"areYouSureYouWantToLogout": "Вы сапраўды хочаце выйсці?",
"yesLogout": "Так, выйсці",
"exit": "Выхад",
"theme": "Тема",
"lightTheme": "Светлая",
"darkTheme": "Цёмная",
"systemTheme": "Сістэманая",
"verifyingRecoveryKey": "Праверка ключа аднаўлення...",
"recoveryKeyVerified": "Ключ аднаўлення правераны",
"recreatePasswordTitle": "Стварыць пароль паўторна",
"invalidKey": "Памылковы ключ",
"tryAgain": "Паспрабуйце яшчэ раз",
"viewRecoveryKey": "Прагледзець ключ аднаўлення",
"confirmRecoveryKey": "Пацвердзіце ключ аднаўлення",
"confirmYourRecoveryKey": "Пацвердзіце свой ключ аднаўлення",
"confirm": "Пацвердзіць",
"emailYourLogs": "Адправіць журналы",
"pleaseSendTheLogsTo": "Адпраўце журналы на \n{toEmail}",
"copyEmailAddress": "Скапіяваць адрас электроннай пошты",
"exportLogs": "Экспартаваць журналы",
"enterYourRecoveryKey": "Увядзіце свой ключ аднаўлення",
"tempErrorContactSupportIfPersists": "Здаецца, што нешта пайшло не так. Паспрабуйце яшчэ раз крыху пазней. Звяжыцеся са службай падтрымкі, калі праблема застанецца.",
"networkHostLookUpErr": "Немагчыма падключыцца да сервера Ente. Праверце свае сеткавыя налады. Звяжыцеся са службай падтрымкі, калі праблема застанецца.",
"about": "Аб праграме",
"weAreOpenSource": "Наша праграма мае адкрыты зыходны код!",
"privacy": "Прыватнасць",
"terms": "Умовы",
"checkForUpdates": "Праверыць абнаўленні",
"checkStatus": "Праверыць статус",
"downloadUpdate": "Спампаваць",
"criticalUpdateAvailable": "Даступна крытычнае абнаўленне",
"updateAvailable": "Даступна абнаўленне",
"update": "Абнавіць",
"checking": "Праверка...",
"youAreOnTheLatestVersion": "У вас апошняя версія праграмы",
"warning": "Папярэджанне",
"exportWarningDesc": "Экспартаваны файл змяшчае канфідэнцыяльныя звесткі. Захоўвайце яго ў надзейным месцы.",
"iUnderStand": "Ясна",
"@iUnderStand": {
"description": "Text for the button to confirm the user understands the warning"
},
"authToExportCodes": "Прайдзіце аўтэнтыфікацыю, каб экспартаваць свае коды",
"importSuccessTitle": "Ура!",
"importSuccessDesc": "Коды паспяхова імпартаваны ({count} шт.)!",
"@importSuccessDesc": {
"placeholders": {
"count": {
"description": "The number of codes imported",
"type": "int",
"example": "1"
}
}
},
"sorry": "Прабачце",
"importFailureDesc": "Не ўдалося прааналізаваць выбраны файл.\nНапішыце нам на support@ente.io, калі вам патрэбная дапамога!",
"pendingSyncs": "Папярэджанне",
"pendingSyncsWarningBody": "Некаторыя вашы коды не былі зарэзерваваны.\n\nПераканайцеся, што ў вас ёсць іх рэзервовая копія перад выхадам з сістэмы.",
"checkInboxAndSpamFolder": "Праверце свае ўваходныя лісты (і спам) для завяршэння праверкі",
"tapToEnterCode": "Націсніце, каб увесці код",
"resendEmail": "Адправіць ліст яшчэ раз",
"manualSort": "Карыстальніцкая",
"editOrder": "Рэдагаваць заказ",
"mostFrequentlyUsed": "Часта выкарыстоўваюцца",
"mostRecentlyUsed": "Нядаўна выкарыстаныя",
"activeSessions": "Актыўныя сеансы",
"terminateSession": "Перарваць сеанс?",
"terminate": "Перарваць",
"thisDevice": "Гэта прылада",
"thisEmailIsAlreadyInUse": "Гэта электронная пошта ўжо выкарыстоўваецца",
"yourVerificationCodeHasExpired": "Ваш праверачны код пратэрмінаваны",
"incorrectCode": "Няправільны код",
"emailChangedTo": "Электронная пошта зменена на {newEmail}",
"authenticationSuccessful": "Аўтэнтыфікацыя паспяхова пройдзена!",
"incorrectRecoveryKey": "Няправільны ключ аднаўлення",
"enterPassword": "Увядзіце пароль",
"selectExportFormat": "Выберыце фармат экспартавання",
"exportDialogDesc": "Зашыфраванае экспартаванне будзе абаронена паролем, які вы выберыце.",
"encrypted": "Зашыфравана",
"plainText": "Звычайны тэкст",
"passwordToEncryptExport": "Пароль для шыфравання экспартавання",
"export": "Экспартаваць",
"useOffline": "Выкарыстоўваць без рэзервовых копій",
"signInToBackup": "Увайсці для рэзервовага капіявання кодаў",
"singIn": "Увайсці",
"sigInBackupReminder": "Экспартуйце свае коды, каб у вас была рэзервовая копія з якой вы заўсёды зможаце аднавіць іх.",
"offlineModeWarning": "Вы выбралі працягнуць без рэзервовых копій. Зрабіце рэзервовую копію кодаў уручную, каб не згубіць доступ да іх.",
"showLargeIcons": "Паказваць вялікі значкі",
"compactMode": "Кампактны рэжым",
"shouldHideCode": "Схаваць коды",
"doubleTapToViewHiddenCode": "Можна двойчы націснуць на запіс, каб паглядзець код",
"focusOnSearchBar": "Сфакусіравацца на пошуку пры запуску праграмы",
"confirmUpdatingkey": "Вы сапраўды хочаце абнавіць сакрэтны ключ?",
"minimizeAppOnCopy": "Згортваць праграму пры капіяванні",
"editCodeAuthMessage": "Прайдзіце аўтэнтыфікацыю, каб рэдагаваць код",
"deleteCodeAuthMessage": "Прайдзіце аўтэнтыфікацыю, каб выдаліць код",
"showQRAuthMessage": "Прайдзіце аўтэнтыфікацыю, каб паказаць QR-код",
"confirmAccountDeleteTitle": "Пацвердзіце выдаленне ўліковага запісу",
"androidBiometricHint": "Праверыць ідэнтыфікацыю",
"@androidBiometricHint": {
"description": "Hint message advising the user how to authenticate with biometrics. It is used on Android side. Maximum 60 characters."
},
"androidBiometricNotRecognized": "Не распазнана. Паспрабуйце яшчэ раз.",
"@androidBiometricNotRecognized": {
"description": "Message to let the user know that authentication was failed. It is used on Android side. Maximum 60 characters."
},
"androidBiometricSuccess": "Паспяхова",
"@androidBiometricSuccess": {
"description": "Message to let the user know that authentication was successful. It is used on Android side. Maximum 60 characters."
@@ -307,22 +223,6 @@
"@androidCancelButton": {
"description": "Message showed on a button that the user can click to leave the current dialog. It is used on Android side. Maximum 30 characters."
},
"androidSignInTitle": "Патрабуецца аўтэнтыфікацыя",
"@androidSignInTitle": {
"description": "Message showed as a title in a dialog which indicates the user that they need to scan biometric to continue. It is used on Android side. Maximum 60 characters."
},
"androidBiometricRequiredTitle": "Патрабуецца біяметрыя",
"@androidBiometricRequiredTitle": {
"description": "Message showed as a title in a dialog which indicates the user has not set up biometric authentication on their device. It is used on Android side. Maximum 60 characters."
},
"androidDeviceCredentialsRequiredTitle": "Патрабуюцца ўліковыя даныя прылады",
"@androidDeviceCredentialsRequiredTitle": {
"description": "Message showed as a title in a dialog which indicates the user has not set up credentials authentication on their device. It is used on Android side. Maximum 60 characters."
},
"androidDeviceCredentialsSetupDescription": "Патрабуюцца ўліковыя даныя прылады",
"@androidDeviceCredentialsSetupDescription": {
"description": "Message advising the user to go to the settings and configure device credentials on their device. It shows in a dialog on Android side."
},
"goToSettings": "Перайсці ў налады",
"@goToSettings": {
"description": "Message showed on a button that the user can click to go to settings pages from the current dialog. It is used on both Android and iOS side. Maximum 30 characters."
@@ -331,24 +231,11 @@
"@iOSOkButton": {
"description": "Message showed on a button that the user can click to leave the current dialog. It is used on iOS side. Maximum 30 characters."
},
"noInternetConnection": "Адсутнічае падключэнне да інтэрнэту",
"signOutFromOtherDevices": "Выйсці з іншых прылад",
"signOutOtherDevices": "Выйсці на іншых прыладах",
"doNotSignOut": "Не выходзіць",
"waitingForBrowserRequest": "Чаканне запыту браўзера...",
"waitingForVerification": "Чаканне праверкі...",
"passkey": "Ключ доступу",
"passKeyPendingVerification": "Праверка пакуль яшчэ не завершана",
"loginSessionExpired": "Сеанс завяршыўся",
"developerSettings": "Налады распрацоўшчыка",
"serverEndpoint": "Канцавы пункт сервера",
"invalidEndpoint": "Памылковы канцавы пункт",
"endpointUpdatedMessage": "Канцавы пункт паспяхова абноўлены",
"customEndpoint": "Падключана да {endpoint}",
"pinText": "Замацаваць",
"unpinText": "Адмацаваць",
"pinnedCodeMessage": "{code} быў замацаваны",
"unpinnedCodeMessage": "{code} быў адмацаваны",
"pinned": "Замацавана",
"tags": "Тэгі",
"createNewTag": "Стварыць новы тэг",
@@ -356,38 +243,23 @@
"create": "Стварыць",
"editTag": "Рэдагаванне тэг",
"deleteTagTitle": "Выдаліць тэг?",
"updateNotAvailable": "Абнаўленне недаступна",
"viewRawCodes": "Паглядзець неапрацаваныя коды",
"rawCodes": "Неапрацаваныя коды",
"rawCodeData": "Неапрацаваныя даныя кода",
"appLock": "Блакіроўка праграмы",
"noSystemLockFound": "Сістэма блакіроўкі не знойдзена",
"autoLock": "Аўтаблакіроўка",
"immediately": "Адразу",
"reEnterPassword": "Увядзіце пароль паўторна",
"reEnterPin": "Увядзіце PIN-код яшчэ раз",
"next": "Далей",
"tooManyIncorrectAttempts": "Занадта шмат няўдалых спроб",
"tapToUnlock": "Націсніце для разблакіроўкі",
"setNewPassword": "Задаць новы пароль",
"deviceLock": "Блакіроўка прылады",
"hideContent": "Схаваць змест",
"pinLock": "Блакіроўка PIN'ам",
"enterPin": "Увядзіце PIN-код",
"setNewPin": "Задаць новы PIN",
"appLockNotEnabled": "Блакіроўка праграмы не ўключана",
"duplicateCodes": "Дублікаты кадоў",
"noDuplicates": "✨ Няма дублікатаў",
"deduplicateCodes": "Дубліраваныя кады",
"deselectAll": "Зняць выбар з усіх",
"selectAll": "Выбраць усе",
"deleteDuplicates": "Выдаліць дублікаты",
"plainHTML": "Звычайны HTML",
"tellUsWhatYouThink": "Раскажыце, што вы думаеце",
"dropReviewiOS": "Пакіньце водгук у App Store",
"dropReviewAndroid": "Пакіньце водгук у Play Store",
"giveUsAStarOnGithub": "Адзначце нас зоркай на Github",
"loginWithAuthAccount": "Увайдзіце з дапамогай уліковага запісу Auth",
"advanced": "Пашыраныя",
"algorithm": "Алгарытм",
"type": "Тып",

View File

@@ -173,7 +173,6 @@
"invalidQRCode": "Codi QR invàlid",
"noRecoveryKeyTitle": "No tens clau de recuperació?",
"enterEmailHint": "Introdueix la teva adreça de correu electrònic",
"enterNewEmailHint": "Introdueix la teva nova adreça de correu electrònic",
"invalidEmailTitle": "Adreça de correu electrònic no vàlida",
"invalidEmailMessage": "Si us plau, introdueix una adreça de correu electrònic vàlida.",
"deleteAccount": "Elimina el compte",
@@ -500,22 +499,16 @@
"appLockOfflineModeWarning": "Has triat procedir sense còpies de seguretat. Si oblides el bloqueig de l'aplicació, no podràs accedir a les teves dades.",
"duplicateCodes": "Codis duplicats",
"noDuplicates": "✨ Sense duplicats",
"youveNoDuplicateCodesThatCanBeCleared": "No teniu cap codi duplicat que es puguin esborrar",
"deduplicateCodes": "Desduplica codis",
"deselectAll": "Desselecciona-ho tot",
"selectAll": "Seleccionar-ho tot",
"deleteDuplicates": "Elimina duplicats",
"plainHTML": "HTML pla",
"tellUsWhatYouThink": "Digueu-nos què us sembla",
"dropReviewiOS": "Deixa una ressenya a l'App Store",
"dropReviewAndroid": "Deixa una ressenya a la Play Store",
"supportEnte": "Donar suport a <bold-green>ente</bold-green>",
"giveUsAStarOnGithub": "Dona'ns una estrella a Github",
"free5GB": "5 GB gratuïts a <bold-green>ente</bold-green> Photos",
"loginWithAuthAccount": "Inicieu sessió amb el vostre compte Auth",
"freeStorageOffer": "10% de descompte a <bold-green>ente</bold-green> photos",
"freeStorageOfferDescription": "Utilitzeu el codi \"AUTH\" per obtenir un 10% de descompte el primer any",
"advanced": "Avançat",
"algorithm": "Algorisme",
"type": "Tipus"
"freeStorageOfferDescription": "Utilitzeu el codi \"AUTH\" per obtenir un 10% de descompte el primer any"
}

View File

@@ -173,7 +173,6 @@
"invalidQRCode": "Código QR no válido",
"noRecoveryKeyTitle": "¿No tienes la clave de recuperación?",
"enterEmailHint": "Introduce tu dirección de correo electrónico",
"enterNewEmailHint": "Introduce tu nueva dirección de correo electrónico",
"invalidEmailTitle": "Dirección de correo electrónico no válida",
"invalidEmailMessage": "Por favor, introduce una dirección de correo electrónico válida.",
"deleteAccount": "Eliminar cuenta",
@@ -514,10 +513,5 @@
"free5GB": "5 GB gratis en <bold-green>ente</bold-green> Fotos",
"loginWithAuthAccount": "Inicia sesión con tu cuenta de Auth",
"freeStorageOffer": "10% de descuento en <bold-green>ente</bold-green> fotos",
"freeStorageOfferDescription": "Usa el cupón \"AUTH\" para obtener un 10% de descuento en el primer año",
"advanced": "Avanzado",
"algorithm": "Algoritmo",
"type": "Tipo",
"period": "Periodo",
"digits": "Dígitos"
"freeStorageOfferDescription": "Usa el cupón \"AUTH\" para obtener un 10% de descuento en el primer año"
}

View File

@@ -11,7 +11,6 @@
"setupFirstAccount": "Lisa oma esimene kasutajakonto",
"importScanQrCode": "Skanneeri QR-koodi",
"qrCode": "QR-kood",
"importEnterSetupKey": "Sisesta seadistusvõti",
"importAccountPageTitle": "Sisesta kasutajakonto üksikasjad",
"secretCanNotBeEmpty": "Saladus ei tohi jääda tühjaks",
"bothIssuerAndAccountCanNotBeEmpty": "Nii kasutajakonto kui väljaandja ei tohi tühjaks jääda",
@@ -33,7 +32,6 @@
}
}
},
"codeAccountHint": "Kasutajakonto (sina@domeen.com)",
"codeTagHint": "Silt",
"accountKeyType": "Võtme tüüp",
"sessionExpired": "Sessioon on aegunud",
@@ -42,12 +40,7 @@
},
"pleaseLoginAgain": "Palun logi uuesti sisse",
"loggingOut": "Väljalogimine...",
"timeBasedKeyType": "Ajapõhine (TOTP)",
"counterBasedKeyType": "Loenduripõhine (HOTP)",
"saveAction": "Salvesta",
"nextTotpTitle": "järgmine",
"deleteCodeTitle": "Kas kustutame koodi?",
"deleteCodeMessage": "Kas sa oled kindel, et soovid selle koodi kustutada? Seda tegevust ei saa tagasi pöörata.",
"trash": "Prügikast",
"viewLogsAction": "Vaata logisid",
"preparingLogsTitle": "Valmistan logisid ette...",
@@ -63,18 +56,7 @@
"copyEmailAction": "Kopeeri e-posti aadress",
"exportLogsAction": "Ekspordi logid",
"reportABug": "Teata veast",
"crashAndErrorReporting": "Teatamine vigadest ja kokkujooksmistest",
"reportBug": "Teata veast",
"emailUsMessage": "Saada meile e-kiri aadressile {email}",
"@emailUsMessage": {
"placeholders": {
"email": {
"type": "String"
}
}
},
"contactSupport": "Võta ühendust klienditoega",
"rateUsOnStore": "Arvusta meid rakendustepoes: {storeName}",
"contactSupport": "Võtke ühendust klienditoega",
"blog": "Blogi",
"verifyPassword": "Korda salasõna",
"pleaseWait": "Palun oota...",
@@ -88,13 +70,8 @@
"changeEmail": "Muuda e-posti aadressi",
"changePassword": "Muuda salasõna",
"data": "Andmed",
"importCodes": "Impordi koode",
"importTypePlainText": "Votmindamata tekstina",
"importTypeEnteEncrypted": "Ente krüptitud ekspordina",
"passwordForDecryptingExport": "Salasõna eksporditud andmete dekrüptimiseks",
"passwordEmptyError": "Salasõna väli ei saa olla tühi",
"importFromApp": "Impordi koodid rakendusest {appName}",
"selectFile": "Vali fail",
"ok": "Sobib",
"cancel": "Katkesta",
"yes": "Jah",

View File

@@ -1 +0,0 @@
{}

View File

@@ -1,28 +1,28 @@
{
"account": "Tài khoản",
"unlock": "Mở khóa",
"recoveryKey": " khôi phục",
"counterAppBarTitle": "Đếm ngược",
"recoveryKey": "Khóa khôi phục",
"counterAppBarTitle": "Bộ Đếm",
"@counterAppBarTitle": {
"description": "Text shown in the AppBar of the Counter Page"
},
"onBoardingBody": "Sao lưu an toàn mã 2FA của bạn",
"onBoardingBody": "Sao lưu mã 2FA của bạn một cách an toàn",
"onBoardingGetStarted": "Bắt đầu",
"setupFirstAccount": "Thiết lập tài khoản đầu tiên của bạn",
"importScanQrCode": "Quét mã QR",
"qrCode": "Mã QR",
"importEnterSetupKey": "Nhập khóa thiết lập",
"importAccountPageTitle": "Nhập chi tiết tài khoản",
"secretCanNotBeEmpty": "Không được để trống khóa bí mật",
"bothIssuerAndAccountCanNotBeEmpty": "Không được để trống dịch vụ và tài khoản",
"incorrectDetails": "Thông tin không chính xác",
"secretCanNotBeEmpty": "Khoá bí mật không được để trống",
"bothIssuerAndAccountCanNotBeEmpty": "Cả nhà phát hành và tài khoản không được để trống",
"incorrectDetails": "Thông tin chi tiết không chính xác",
"pleaseVerifyDetails": "Vui lòng xác minh chi tiết và thử lại",
"codeIssuerHint": "Dịch vụ",
"codeIssuerHint": "Bên phát hành",
"codeSecretKeyHint": "Khóa bí mật",
"secret": "Khóa bí mật",
"all": "Tất cả",
"notes": "Ghi chú",
"notesLengthLimit": "Ghi chú dài tối đa {count} ký tự",
"notesLengthLimit": "Ghi chú có thể dài tối đa {count} ký tự",
"@notesLengthLimit": {
"description": "Text to indicate the maximum number of characters allowed for notes",
"placeholders": {
@@ -33,10 +33,10 @@
}
}
},
"codeAccountHint": "Tài khoản (you@domain.com)",
"codeAccountHint": "Tài khoản (bạn@miền.com)",
"codeTagHint": "Thẻ",
"accountKeyType": "Loại khóa",
"sessionExpired": "Phiên đăng nhập đã hết hạn",
"sessionExpired": "Phiên làm việc đã hết hạn",
"@sessionExpired": {
"description": "Title of the dialog when the users current session is invalid/expired"
},
@@ -47,15 +47,15 @@
"saveAction": "Lưu",
"nextTotpTitle": "tiếp theo",
"deleteCodeTitle": "Xóa mã?",
"deleteCodeMessage": "Bạn có chắc muốn xóa mã này không? Hành động này không thể hoàn tác.",
"deleteCodeMessage": "Bạn có chắc chắn muốn xóa mã này không? Hành động này không thể đảo ngược.",
"trashCode": "Xóa mã?",
"trashCodeMessage": "Bạn có chắc muốn xóa mã cho {account} không?",
"trashCodeMessage": "Bạn có chắc chắn muốn xóa mã cho {account} không?",
"trash": "Xóa",
"viewLogsAction": "Xem nhật ký",
"sendLogsDescription": "Gửi nhật ký để giúp chúng tôi xử lý vấn đề của bạn. Dù chúng tôi thực hiện các biện pháp phòng ngừa để đảm bảo rằng thông tin nhạy cảm không được ghi lại, bạn vẫn nên xem các nhật ký này trước khi chia sẻ chúng.",
"preparingLogsTitle": "Đang ghi nhật ký...",
"sendLogsDescription": "Thao tác này sẽ gửi nhật ký để giúp chúng tôi gỡ lỗi sự cố của bạn. Mặc dù chúng tôi thực hiện các biện pháp phòng ngừa để đảm bảo rằng thông tin nhạy cảm không được ghi lại, nhưng chúng tôi khuyến khích bạn xem các nhật ký này trước khi chia sẻ chúng.",
"preparingLogsTitle": "Đang chuẩn bị nhật ký...",
"emailLogsTitle": "Nhật ký email",
"emailLogsMessage": "Vui lòng gửi nhật ký đến {email}",
"emailLogsMessage": "Vui lòng gửi nhật ký tới {email}",
"@emailLogsMessage": {
"placeholders": {
"email": {
@@ -65,7 +65,7 @@
},
"copyEmailAction": "Sao chép email",
"exportLogsAction": "Xuất nhật ký",
"reportABug": "Báo lỗi",
"reportABug": "Báo cáo lỗi",
"crashAndErrorReporting": "Báo cáo sự cố & lỗi",
"reportBug": "Báo lỗi",
"emailUsMessage": "Vui lòng gửi email cho chúng tôi tại {email}",
@@ -79,88 +79,88 @@
"contactSupport": "Liên hệ hỗ trợ",
"rateUsOnStore": "Đánh giá chúng tôi trên {storeName}",
"blog": "Blog",
"merchandise": "Vật phẩm",
"verifyPassword": "Xác minh mật khẩu",
"merchandise": "Hàng hóa",
"verifyPassword": "Xác nhận mật khẩu",
"pleaseWait": "Vui lòng chờ...",
"generatingEncryptionKeysTitle": "Đang tạo khóa mã hóa...",
"recreatePassword": "Tạo lại mật khẩu",
"recreatePasswordMessage": "Thiết bị hiện tại không đủ mạnh để xác minh mật khẩu của bạn, nhưng chúng tôi có thể tạo lại để nó hoạt động với tất cả thiết bị.\n\nVui lòng đăng nhập bằng khôi phục và tạo lại mật khẩu (bạn có thể ng lại mật khẩu nếu muốn).",
"useRecoveryKey": "Dùng khôi phục",
"recreatePasswordMessage": "Thiết bị hiện tại không đủ mạnh để xác minh mật khẩu của bạn, vì vậy chúng tôi cần tạo lại mật khẩu một lần theo cách hoạt động với tất cả các thiết bị.\n\nVui lòng đăng nhập bằng khóa khôi phục và tạo lại mật khẩu của bạn (bạn có thể sử dụng lại cùng một mật khẩu nếu muốn).",
"useRecoveryKey": "Dùng khóa khôi phục",
"incorrectPasswordTitle": "Mật khẩu không đúng",
"welcomeBack": "Chào mừng trở lại!",
"emailAlreadyRegistered": "Email đã được đăng ký.",
"emailNotRegistered": "Email chưa được đăng ký.",
"madeWithLoveAtPrefix": "lập trình bằng ❤️ bởi ",
"emailAlreadyRegistered": "Email đã được đăng kí.",
"emailNotRegistered": "Email chưa được đăng kí.",
"madeWithLoveAtPrefix": "được làm bằng ❤️ tại ",
"supportDevs": "Đăng ký <bold-green>ente</bold-green> để hỗ trợ dự án này.",
"supportDiscount": "Dùng mã \"AUTH\" để được giảm 10% trong năm đầu tiên",
"changeEmail": "Đổi email",
"supportDiscount": "Sử dụng mã giảm giá \"AUTH\" để được giảm 10% trong năm đầu tiên",
"changeEmail": "Thay đổi email",
"changePassword": "Đổi mật khẩu",
"data": "Dữ liệu",
"importCodes": "Nhập mã",
"importTypePlainText": "Văn bản thuần",
"importTypeEnteEncrypted": "Ente Auth",
"passwordForDecryptingExport": "Mật khẩu để giải mã tệp xuất",
"importTypeEnteEncrypted": "Xuất key đã được mã hóa",
"passwordForDecryptingExport": "Mật khẩu để giải mã xuất",
"passwordEmptyError": "Mật khẩu không thể để trống",
"importFromApp": "Nhập mã từ {appName}",
"importGoogleAuthGuide": "Xuất dữ liệu tài khoản Google Authenticator của bạn thành mã QR bằng tùy chọn \"Chuyển tài khoản\". Sau đó, dùng thiết bị khác quét mã QR.",
"importGoogleAuthGuide": "Xuất dữ liệu tài khoản của bạn từ Google Authenticator sang mã QR bằng tùy chọn \"Chuyển tài khoản\". Sau đó dùng thiết bị khác quét mã QR.",
"importSelectJsonFile": "Chọn tệp JSON",
"importSelectAppExport": "Chọn tệp xuất từ {appName}",
"importEnteEncGuide": "Chọn tệp JSON Ente đã mã hóa",
"importRaivoGuide": "ng tùy chọn \"Xuất OTP thành tệp Zip\" của Raivo.\n\nGiải nén tệp Zip đó và nhập tệp JSON.",
"importBitwardenGuide": "ng tùy chọn \"Xuất kho\" của Bitwarden và nhập tệp JSON không có mã hóa.",
"importAegisGuide": "Dùng tùy chọn \"Xuất kho\" của Aegis.\n\nNếu kho của bạn có mã hóa, bạn phải có mật khẩu để giải mã.",
"import2FasGuide": "ng tùy chọn \"Cài đặt->Sao lưu -Xuất dữ liệu\" của 2FAS.\n\nNếu bản sao lưu của bạn có mã hóa, bạn phải có mật khẩu để giải mã.",
"importLastpassGuide": "ng tùy chọn \"Chuyển tài khoản\" của Lastpass Authenticator và nhấn \"Xuất tài khoản ra tệp\". Nhập tệp JSON đã tải xuống.",
"importSelectAppExport": "Chọn {appName} tệp dữ liệu xuất",
"importEnteEncGuide": "Chọn tệp JSON được mã hóa đã xuất từ ente",
"importRaivoGuide": "Sử dụng tùy chọn \"Xuất OTP sang lưu trữ Zip\" trong cài đặt của Raivo.",
"importBitwardenGuide": "Sử dụng tùy chọn \"Xuất vault\" trong công cụ Bitwarden và nhập tệp JSON không được mã hóa.",
"importAegisGuide": "Nếu vault của bạn được mã hóa, bạn sẽ cần nhập mật khẩu vault để giải mã vault.",
"import2FasGuide": "Sử dụng tùy chọn \"Cài đặt->Sao lưu -Xuất dữ liệu\" trong 2FAS.\n\nNếu bản sao lưu của bạn được mã hóa, bạn sẽ cần nhập mật khẩu để giải mã bản sao lưu",
"importLastpassGuide": "Sử dụng tùy chọn \"Chuyển tài khoản\" trong Cài đặt Lastpass Authenticator và nhấn \"Xuất tài khoản ra tệp\". Nhập tệp JSON đã tải xuống.",
"exportCodes": "Xuất mã",
"importLabel": "Nhập",
"importInstruction": "Vui lòng chọn tệp chứa danh sách mã của bạn định dạng",
"importCodeDelimiterInfo": "Phân tách bằng dấu phẩy hoặc xuống dòng",
"selectFile": "Chọn tệp",
"emailVerificationToggle": "Xác minh email",
"importInstruction": "Vui lòng chọn tệp chứa danh sách mã của bạn định dạng sau",
"importCodeDelimiterInfo": "Các mã có thể được phân tách bằng một dấu phẩy hoặc một dòng mới",
"selectFile": "Chọn tập tin",
"emailVerificationToggle": "Email xác thực",
"emailVerificationEnableWarning": "Để tránh bị khóa tài khoản, hãy đảm bảo lưu trữ bản sao email 2FA của bạn bên ngoài Ente Auth trước khi bật xác minh email.",
"authToChangeEmailVerificationSetting": "Vui lòng xác thực để đổi email",
"authToChangeEmailVerificationSetting": "Vui lòng xác thực để thay đổi email",
"authenticateGeneric": "Vui lòng xác thực",
"authToViewYourRecoveryKey": "Vui lòng xác thực để xem khôi phục",
"authToViewYourRecoveryKey": "Vui lòng xác thực để xem khóa khôi phục của bạn",
"authToChangeYourEmail": "Vui lòng xác thực để thay đổi email của bạn",
"authToChangeYourPassword": "Vui lòng xác thực để đổi mật khẩu",
"authToViewSecrets": "Vui lòng xác thực để xem khóa bí mật",
"authToInitiateSignIn": "Vui lòng xác thực để bắt đầu sao lưu",
"ok": "Được",
"authToChangeYourPassword": "Vui lòng xác thực để thay đổi mật khẩu của bạn",
"authToViewSecrets": "Vui lòng xác thực để xem bí mật của bạn",
"authToInitiateSignIn": "Vui lòng xác thực để bắt đầu đăng nhập nhằm sao lưu.",
"ok": "Đồng ý",
"cancel": "Hủy",
"yes": "",
"yes": "Đúng",
"no": "Không",
"email": "Email",
"email": "Thư điện tử",
"support": "Hỗ trợ",
"general": "Chung",
"general": "Tổng quan",
"settings": "Cài đặt",
"copied": "Đã sao chép",
"pleaseTryAgain": "Vui lòng thử lại",
"existingUser": "Đã có tài khoản",
"newUser": "Mới dùng Ente",
"existingUser": "Người dùng hiện tại",
"newUser": "Mới tham gia Ente",
"delete": "Xóa",
"enterYourPasswordHint": "Nhập mật khẩu của bạn",
"forgotPassword": "Quên mật khẩu",
"oops": "Ốii!",
"suggestFeatures": "Đề xuất tính năng",
"oops": "Rất tiếc",
"suggestFeatures": "Gợi ý tính năng",
"faq": "Câu hỏi thường gặp",
"somethingWentWrongMessage": "Có gì đó không ổn, vui lòng thử lại",
"leaveFamily": "Rời khỏi gói gia đình",
"leaveFamilyMessage": "Bạn có chắc muốn rời khỏi gói gia đình không?",
"inFamilyPlanMessage": "Bạn đang ng gói gia đình!",
"hintForMobile": "Nhấn giữ mã để chỉnh sửa hoặc xóa.",
"hintForDesktop": "Nhấn chuột phải vào mã để chỉnh sửa hoặc xóa.",
"somethingWentWrongMessage": "Đã xảy ra lỗi, xin thử lại",
"leaveFamily": "Rời khỏi gia đình",
"leaveFamilyMessage": "Bạn có chắc chắn muốn thoát khỏi gói dành cho gia đình không?",
"inFamilyPlanMessage": "Bạn đang sử dụng gói dành cho gia đình!",
"hintForMobile": "Nhấn giữ trên mã để chỉnh sửa hoặc xóa.",
"hintForDesktop": "Nhấp chuột phải vào mã để chỉnh sửa hoặc xóa.",
"scan": "Quét",
"scanACode": "Quét mã",
"verify": "Xác minh",
"verifyEmail": "Xác minh email",
"enterCodeHint": "Nhập mã 6 chữ số từ\nứng dụng xác thực của bạn",
"verifyEmail": "Xác nhận địa chỉ Email",
"enterCodeHint": "Nhập mã gồm 6 chữ số từ ứng dụng xác thực của bạn",
"lostDeviceTitle": "Mất thiết bị?",
"twoFactorAuthTitle": "Xác thực 2 bước",
"passkeyAuthTitle": "Xác minh khóa truy cập",
"verifyPasskey": "Xác minh khóa truy cập",
"twoFactorAuthTitle": "Xác thực hai yếu tố",
"passkeyAuthTitle": "Xác minh khóa",
"verifyPasskey": "Xác minh khóa",
"loginWithTOTP": "Đăng nhập bằng TOTP",
"recoverAccount": "Khôi phục tài khoản",
"enterRecoveryKeyHint": "Nhập khôi phục của bạn",
"enterRecoveryKeyHint": "Nhập khóa khôi phục của bạn",
"recover": "Khôi phục",
"contactSupportViaEmailMessage": "Vui lòng gửi email đến {email} từ địa chỉ email đã đăng ký của bạn",
"@contactSupportViaEmailMessage": {
@@ -171,13 +171,12 @@
}
},
"invalidQRCode": "Mã QR không hợp lệ",
"noRecoveryKeyTitle": "Không có khôi phục?",
"noRecoveryKeyTitle": "Không có khóa khôi phục?",
"enterEmailHint": "Nhập địa chỉ email của bạn",
"enterNewEmailHint": "Nhập địa chỉ email mới của bạn",
"invalidEmailTitle": "Địa chỉ email không hợp lệ",
"invalidEmailMessage": "Vui lòng nhập một địa chỉ email hợp lệ.",
"deleteAccount": "Xóa tài khoản",
"deleteAccountQuery": "Chúng tôi rất tiếc khi thấy bạn ra đi. Có phải bạn gặp vấn đề?",
"invalidEmailMessage": "Xin vui lòng nhập một địa chỉ email hợp lệ.",
"deleteAccount": "X tài khoản",
"deleteAccountQuery": "Chúng tôi sẽ rất tiếc khi thấy bạn đi. Bạn đang phải đối mặt với một số vấn đề?",
"yesSendFeedbackAction": "Có, gửi phản hồi",
"noDeleteAccountAction": "Không, xóa tài khoản",
"initiateAccountDeleteTitle": "Vui lòng xác thực để bắt đầu xóa tài khoản",
@@ -188,40 +187,40 @@
"moderateStrength": "Trung bình",
"confirmPassword": "Xác nhận mật khẩu",
"close": "Đóng",
"oopsSomethingWentWrong": "Ốii!, có gì đó không ổn.",
"oopsSomethingWentWrong": "Rất tiếc, Đã xảy ra lỗi.",
"selectLanguage": "Chọn ngôn ngữ",
"language": "Ngôn ngữ",
"social": "Mạng xã hội",
"social": "Xã hội",
"security": "Bảo mật",
"lockscreen": "Khóa màn hình",
"authToChangeLockscreenSetting": "Vui lòng xác thực để thay đổi cài đặt khóa màn hình",
"lockscreen": "Màn hình khoá",
"authToChangeLockscreenSetting": "Vui lòng xác thực để thay đổi cài đặt màn hình khóa",
"deviceLockEnablePreSteps": "Để bật khoá thiết bị, vui lòng thiết lập mật khẩu thiết bị hoặc khóa màn hình trong cài đặt hệ thống của bạn.",
"viewActiveSessions": "Xem phiên hoạt động",
"authToViewYourActiveSessions": "Vui lòng xác thực để xem các phiên hoạt động",
"viewActiveSessions": "Xem danh sách phiên làm việc hiện tại",
"authToViewYourActiveSessions": "Vui lòng xác thực để xem danh sách phiên làm việc của bạn",
"searchHint": "Tìm kiếm...",
"search": "Tìm kiếm",
"sorryUnableToGenCode": "Rất tiếc, không thể tạo mã cho {issuerName}",
"noResult": "Không có kết quả",
"addCode": "Thêm mã",
"scanAQrCode": "Quét mã QR",
"enterDetailsManually": "Nhập thủ công",
"enterDetailsManually": "Nhập chi tiết thủ công",
"edit": "Sửa",
"share": "Chia sẻ",
"shareCodes": "Chia sẻ mã",
"shareCodesDuration": "Chọn thời hạn bạn muốn chia sẻ mã.",
"shareCodesDuration": "Chọn khoảng thời gian mà bạn muốn chia sẻ mã.",
"restore": "Khôi phục",
"copiedToClipboard": "Đã sao chép vào bộ nhớ tạm",
"copiedNextToClipboard": "Đã sao chép mã tiếp theo vào b nhớ tạm",
"copiedToClipboard": "Đ sao chp vào khay nhớ tạm",
"copiedNextToClipboard": "Đã sao chép mã tiếp theo vào bảng nhớ tạm",
"error": "Lỗi",
"recoveryKeyCopiedToClipboard": "Đã sao chép khôi phục vào bộ nhớ tạm",
"recoveryKeyOnForgotPassword": "Nếu bạn quên mật khẩu, cách duy nhất để khôi phục dữ liệu của bạn là dùng mã này.",
"recoveryKeySaveDescription": "Chúng tôi không lưu trữ này, nên hãy lưu nó ở nơi an toàn.",
"recoveryKeyCopiedToClipboard": "Đã sao chép khóa khôi phục vào bộ nhớ tạm",
"recoveryKeyOnForgotPassword": "Nếu bạn quên mật khẩu, cách duy nhất bạn có thể khôi phục dữ liệu của mình là sử dụng khóa này.",
"recoveryKeySaveDescription": "Chúng tôi không lưu trữ khóa này, vui lòng lưu khóa 24 từ này ở nơi an toàn.",
"doThisLater": "Để sau",
"saveKey": "Lưu ",
"saveKey": "Lưu khóa",
"save": "Lưu",
"send": "Gửi",
"saveOrSendDescription": "Bạn muốn lưu vào bộ nhớ (Mặc định là thư mục Tải xuống) hay gửi qua ứng dụng khác?",
"saveOnlyDescription": "Bạn muốn lưu vào bộ nhớ (Mặc định là thư mục Tải xuống)?",
"saveOrSendDescription": "Bạn muốn lưu vào bộ nhớ (Mặc định lưu vào thư mục Tải về) hoặc chuyển qua ứng dụng khác?",
"saveOnlyDescription": "Bạn muốn lưu vào bộ nhớ không (Mặc định lưu vào thư mục Tải về)?",
"back": "Quay lại",
"createAccount": "Tạo tài khoản",
"passwordStrength": "Độ mạnh mật khẩu: {passwordStrengthValue}",
@@ -237,76 +236,76 @@
"message": "Password Strength: {passwordStrengthText}"
},
"password": "Mật khẩu",
"signUpTerms": "Tôi đồng ý với <u-terms>điều khoản</u-terms> và <u-policy>chính sách bảo mật</u-policy>",
"signUpTerms": "Tôi đồng ý với <u-terms>điều khoản dịch vụ</u-terms> và <u-policy>chính sách quyền riêng tư</u-policy>",
"privacyPolicyTitle": "Chính sách bảo mật",
"termsOfServicesTitle": "Điều khoản",
"encryption": "Mã hóa",
"setPasswordTitle": "Đặt mật khẩu",
"changePasswordTitle": "Đổi mật khẩu",
"changePasswordTitle": "Thay đổi mật khẩu",
"resetPasswordTitle": "Đặt lại mật khẩu",
"encryptionKeys": "Khóa mã hóa",
"passwordWarning": "Chúng tôi không lưu trữ mật khẩu này, nên nếu bạn quên, <underline>chúng tôi không thể giải mã dữ liệu của bạn</underline>",
"enterPasswordToEncrypt": "Vui lòng nhập một mật khẩu dùng để mã hóa dữ liệu của bạn",
"enterNewPasswordToEncrypt": "Vui lòng nhập một mật khẩu mới để mã hóa dữ liệu của bạn",
"passwordChangedSuccessfully": "Đã thay đổi mật khẩu thành công",
"passwordWarning": "Chúng tôi không lưu trữ mật khẩu này, vì vậy nếu bạn quên, <underline>chúng tôi không thể giải mã dữ liệu của bạn</underline>",
"enterPasswordToEncrypt": "Nhập mật khẩu mà chúng tôi có thể sử dụng để mã hóa dữ liệu của bạn",
"enterNewPasswordToEncrypt": "Nhập một mật khẩu mới mà chúng tôi có thể sử dụng để mã hóa dữ liệu của bạn",
"passwordChangedSuccessfully": "Thay đổi mật khẩu thành công",
"generatingEncryptionKeys": "Đang tạo khóa mã hóa...",
"continueLabel": "Tiếp tục",
"insecureDevice": "Thiết bị không an toàn",
"sorryWeCouldNotGenerateSecureKeysOnThisDevicennplease": "Rất tiếc, chúng tôi không thể tạo khóa an toàn trên thiết bị này.\n\nVui lòng đăng ký từ một thiết bị khác.",
"sorryWeCouldNotGenerateSecureKeysOnThisDevicennplease": "Rất tiếc, chúng tôi không thể tạo khóa bảo mật trên thiết bị này.\n\nvui lòng đăng ký từ một thiết bị khác.",
"howItWorks": "Cách thức hoạt động",
"ackPasswordLostWarning": "Tôi hiểu rằng nếu mất mật khẩu, dữ liệu của tôi sẽ mất vì nó được <underline>mã hóa đầu cuối</underline>.",
"loginTerms": "Nhấn vào đăng nhập, tôi đồng ý với <u-terms>điều khoản</u-terms> và <u-policy>chính sách bảo mật</u-policy>",
"ackPasswordLostWarning": "Tôi hiểu rằng việc mất mật khẩu có thể đồng nghĩa với việc mất dữ liệu của tôi vì dữ liệu của tôi được <underline>mã hóa hai đầu</underline>.",
"loginTerms": "Bằng cách nhấp vào đăng nhập, tôi đồng ý với <u-terms>điều khoản dịch vụ</u-terms> và <u-policy>chính sách quyền riêng tư</u-policy>",
"logInLabel": "Đăng nhập",
"logout": "Đăng xuất",
"areYouSureYouWantToLogout": "Bạn có chắc muốn đăng xuất không?",
"areYouSureYouWantToLogout": "Bạn có chắc chắn muốn đăng xuất?",
"yesLogout": "Có, đăng xuất",
"exit": "Thoát",
"theme": "Chủ đề",
"lightTheme": "Sáng",
"darkTheme": "Tối",
"systemTheme": "Giống hệ thống",
"verifyingRecoveryKey": "Đang xác minh khôi phục...",
"recoveryKeyVerified": " khôi phục đã được xác minh",
"recoveryKeySuccessBody": "Tuyệt! Mã khôi phục của bạn hợp lệ. Cảm ơn đã xác minh.\n\nNhớ lưu giữ mã khôi phục của bạn ở nơi an toàn.",
"invalidRecoveryKey": " khôi phục không hợp lệ. Vui lòng đảm bảo nó chứa 24 từ,đúng chính tả từng từ.\n\nNếu bạn nhập loại mã khôi phục cũ, hãy đảm bảo nó dài 64 ký tự, và kiểm tra từng ký tự.",
"systemTheme": "Hệ thống",
"verifyingRecoveryKey": "Đang xác minh khóa khôi phục...",
"recoveryKeyVerified": "Khóa khôi phục đã được xác thực",
"recoveryKeySuccessBody": "Tuyệt vời! Khóa khôi phục của bạn hợp lệ. Cảm ơn bạn đã xác minh.\n\nHãy nhớ sao lưu khóa khôi phục của bạn một cách an toàn.",
"invalidRecoveryKey": "Khóa khôi phục bạn đã nhập không hợp lệ. Vui lòng đảm bảo rằng nó chứa 24 từ và kiểm tra chính tả của từng từ.\n\nNếu bạn đã nhập mã khôi phục cũ hơn, hãy đảm bảo mã đó dài 64 ký tự và kiểm tra từng ký tự.",
"recreatePasswordTitle": "Tạo lại mật khẩu",
"recreatePasswordBody": "Thiết bị hiện tại không đủ mạnh để xác minh mật khẩu của bạn, nhưng chúng tôi có thể tạo lại để nó hoạt động với tất cả thiết bị.\n\nVui lòng đăng nhập bằng khôi phục và tạo lại mật khẩu (bạn có thể dùng lại mật khẩu nếu muốn).",
"invalidKey": " không hợp lệ",
"recreatePasswordBody": "Thiết bị hiện tại không đủ mạnh để xác minh mật khẩu của bạn nhưng chúng tôi có thể tạo lại mật khẩu theo cách hoạt động với tất cả các thiết bị.\n\nVui lòng đăng nhập bằng khóa khôi phục và tạo lại mật khẩu của bạn (bạn có thể sử dng lại cùng một mật khẩu nếu muốn).",
"invalidKey": "Khoá không hợp lệ",
"tryAgain": "Thử lại",
"viewRecoveryKey": "Xem mã khôi phục",
"confirmRecoveryKey": "Xác nhận khôi phục",
"recoveryKeyVerifyReason": " khôi phục là cách duy nhất để khôi phục ảnh của bạn nếu bạn quên mật khẩu. Bạn có thể xem mã khôi phục của mình trong Cài đặt > Tài khoản.\n\nVui lòng nhập khôi phục của bạn đây để xác minh rằng bạn đã lưu nó đúng cách.",
"confirmYourRecoveryKey": "Xác nhận khôi phục của bạn",
"viewRecoveryKey": "Hiển thị khóa khôi phục",
"confirmRecoveryKey": "Xác nhận khóa khôi phục",
"recoveryKeyVerifyReason": "Nếu bạn quên mật khẩu, khóa khôi phục là cách duy nhất để khôi phục ảnh của bạn. Bạn có thể tìm thấy khóa khôi phục của mình trong Cài đặt > Tài khoản.\n\nVui lòng nhập khóa khôi phục của bạn tại đây để xác minh rằng bạn đã lưu chính xác.",
"confirmYourRecoveryKey": "Xác nhận khóa khôi phục",
"confirm": "Xác nhận",
"emailYourLogs": "Gửi nhật ký qua email",
"emailYourLogs": "Gửi email nhật ký của bạn",
"pleaseSendTheLogsTo": "Vui lòng gửi nhật ký đến \n{toEmail}",
"copyEmailAddress": "Sao chép địa chỉ email",
"exportLogs": "Xuất nhật ký",
"enterYourRecoveryKey": "Nhập khôi phục của bạn",
"tempErrorContactSupportIfPersists": "Có vẻ đã xảy ra sự cố. Vui lòng thử lại sau ít phút. Nếu lỗi vẫn tiếp diễn, hãy liên hệ với đội ngũ hỗ trợ của chúng tôi.",
"networkHostLookUpErr": "Không thể kết nối với Ente, vui lòng kiểm tra cài đặt mạng của bạn và liên hệ vi bộ phận hỗ trợ nếu lỗi vẫn tiếp diễn.",
"networkConnectionRefusedErr": "Không thể kết nối với Ente, vui lòng thử lại sau ít phút. Nếu lỗi vẫn tiếp diễn, hãy liên hệ với bộ phận hỗ trợ.",
"itLooksLikeSomethingWentWrongPleaseRetryAfterSome": "Có vẻ đã xảy ra sự cố. Vui lòng thử lại sau ít phút. Nếu lỗi vẫn tiếp diễn, hãy liên hệ với đội ngũ hỗ trợ của chúng tôi.",
"about": "Giới thiệu",
"weAreOpenSource": "Chúng tôi mã nguồn mở!",
"enterYourRecoveryKey": "Nhập khóa khôi phục của bạn",
"tempErrorContactSupportIfPersists": "Có vẻ như đã xảy ra sự cố. Vui lòng thử lại sau một thời gian. Nếu lỗi vẫn tiếp diễn, vui lòng liên hệ với nhóm hỗ trợ của chúng tôi.",
"networkHostLookUpErr": "Không thể kết nối đến Ente, vui lòng kiểm tra lại kết nối mạng. Nếu vẫn còn lỗi, xin vui lòng liên hệ hỗ trợ.",
"networkConnectionRefusedErr": "Không thể kết nối đến Ente, vui lòng thử lại sau. Nếu vẫn còn lỗi, xin vui lòng liên hệ hỗ trợ.",
"itLooksLikeSomethingWentWrongPleaseRetryAfterSome": "Có vẻ như đã xảy ra sự cố. Vui lòng thử lại sau một thời gian. Nếu lỗi vẫn tiếp diễn, vui lòng liên hệ với nhóm hỗ trợ của chúng tôi.",
"about": "Về chúng tôi",
"weAreOpenSource": "Chúng tôi mã nguồn mở!",
"privacy": "Riêng tư",
"terms": "Điều khoản",
"checkForUpdates": "Kiểm tra cập nhật",
"checkStatus": "Kiểm tra trạng thái",
"downloadUpdate": "Tải xuống",
"criticalUpdateAvailable": "Cập nhật quan trọng có sẵn",
"updateAvailable": "Cập nhật có sẵn",
"criticalUpdateAvailable": "Đã có bản cập nhật quan trọng",
"updateAvailable": "Đã có bản cập nhật",
"update": "Cập nhật",
"checking": "Đang kiểm tra...",
"youAreOnTheLatestVersion": "Bạn đang sử dụng phiên bản mới nhất",
"warning": "Cnh báo",
"exportWarningDesc": "Tệp xuất chứa thông tin nhạy cảm. Hãy lưu trữ tệp này một cách an toàn.",
"warning": "Cánh báo",
"exportWarningDesc": "Tệp đã xuất chứa thông tin nhạy cảm. Hãy lưu trữ tệp này một cách an toàn.",
"iUnderStand": "Tôi hiểu",
"@iUnderStand": {
"description": "Text for the button to confirm the user understands the warning"
},
"authToExportCodes": "Vui lòng xác thực để xuất mã",
"importSuccessTitle": "Tuyệt!",
"authToExportCodes": "Vui lòng xác thực để xuất mã của bạn",
"importSuccessTitle": "Hoan hô!",
"importSuccessDesc": "Bạn đã nhập {count} mã!",
"@importSuccessDesc": {
"placeholders": {
@@ -317,14 +316,14 @@
}
}
},
"sorry": "Rất tiếc",
"importFailureDesc": "Không thể phân tích tệp đã chọn.\nVui lòng liên hệ support@ente.io nếu bạn cần trợ giúp!",
"pendingSyncs": "Cnh báo",
"sorry": "Xin lỗi",
"importFailureDesc": "Không thể phân tích cú pháp tệp đã chọn.\nVui lòng viết thư cho support@ente.io nếu bạn cần trợ giúp!",
"pendingSyncs": "Cánh báo",
"pendingSyncsWarningBody": "Một số mã của bạn chưa được sao lưu.\n\nVui lòng đảm bảo rằng bạn có bản sao lưu cho các mã này trước khi đăng xuất.",
"checkInboxAndSpamFolder": "Vui lòng kiểm tra hộp thư đến (và thư rác) để hoàn tất xác minh",
"tapToEnterCode": "Nhấn để nhập mã",
"checkInboxAndSpamFolder": "Vui lòng kiểm tra hộp thư đến (và thư rác) của bạn để hoàn tất xác minh",
"tapToEnterCode": "Chạm để nhập mã",
"resendEmail": "Gửi lại email",
"weHaveSendEmailTo": "Chúng tôi đã gửi một email đến <green>{email}</green>",
"weHaveSendEmailTo": "Chúng tôi đã gửi thư đến <green>{email}</green>",
"@weHaveSendEmailTo": {
"description": "Text to indicate that we have sent a mail to the user",
"placeholders": {
@@ -336,57 +335,57 @@
}
},
"manualSort": "Tùy chỉnh",
"editOrder": "Chỉnh sửa thứ tự",
"editOrder": "Chỉnh sửa đơn hàng",
"mostFrequentlyUsed": "Thường dùng",
"mostRecentlyUsed": "Dùng gần đây",
"activeSessions": "Phiên hoạt động",
"somethingWentWrongPleaseTryAgain": "Có gì đó không ổn, vui lòng thử lại",
"thisWillLogYouOutOfThisDevice": "Bạn sẽ đăng xuất khỏi thiết bị này!",
"thisWillLogYouOutOfTheFollowingDevice": "Bạn cũng sẽ đăng xuất khỏi những thiết bị sau:",
"activeSessions": "Các phiên làm việc hiện tại",
"somethingWentWrongPleaseTryAgain": "Phát hiện có lỗi, xin thử lại",
"thisWillLogYouOutOfThisDevice": "Thao tác này sẽ đăng xuất bạn khỏi thiết bị này!",
"thisWillLogYouOutOfTheFollowingDevice": "Thao tác này sẽ đăng xuất bạn khỏi thiết bị sau:",
"terminateSession": "Kết thúc phiên?",
"terminate": "Kết thúc",
"thisDevice": "Thiết bị này",
"toResetVerifyEmail": "Để đặt lại mật khẩu, vui lòng xác minh email của bạn trước.",
"thisEmailIsAlreadyInUse": "Email này đã được sử dụng",
"verificationFailedPleaseTryAgain": "Xác minh không thành công, vui lòng thử lại",
"verificationFailedPleaseTryAgain": "Mã xác nhận thất bại. Vui lòng thử lại",
"yourVerificationCodeHasExpired": "Mã xác minh của bạn đã hết hạn",
"incorrectCode": "Mã không chính xác",
"sorryTheCodeYouveEnteredIsIncorrect": "Rất tiếc, mã bạn nhập không chính xác",
"emailChangedTo": "Email đã được đổi thành {newEmail}",
"authenticationFailedPleaseTryAgain": "Xác thực không thành công, vui lòng thử lại",
"sorryTheCodeYouveEnteredIsIncorrect": "Xin lỗi, mã bạn đã nhập không chính xác",
"emailChangedTo": "Thay đổi email thành {newEmail}",
"authenticationFailedPleaseTryAgain": "Xác thực lỗi, vui lòng thử lại",
"authenticationSuccessful": "Xác thực thành công!",
"twofactorAuthenticationSuccessfullyReset": "Xác thực 2 bước đã được đặt lại thành công",
"incorrectRecoveryKey": " khôi phục không chính xác",
"theRecoveryKeyYouEnteredIsIncorrect": " khôi phục bạn nhập không chính xác",
"twofactorAuthenticationSuccessfullyReset": "Xác thực hai bước được khôi phục thành công",
"incorrectRecoveryKey": "Khóa khôi phục không chính xác",
"theRecoveryKeyYouEnteredIsIncorrect": "Khóa khôi phục bạn đã nhập không chính xác",
"enterPassword": "Nhập mật khẩu",
"selectExportFormat": "Chọn định dạng dữ liệu xuất",
"exportDialogDesc": "Dữ liệu xuất được mã hóa sẽ được bảo vệ bằng mật khẩu bạn chọn.",
"encrypted": "Được mã hóa",
"exportDialogDesc": "Xuất dữ liệu được mã hóa sẽ được bảo vệ bằng mật khẩu bạn chọn.",
"encrypted": "Đã mã hóa",
"plainText": "Văn bản thuần",
"passwordToEncryptExport": "Mật khẩu để giải mã dữ liệu xuất",
"export": "Xuất",
"export": "Xuất dữ liệu",
"useOffline": "Sử dụng mà không sao lưu",
"signInToBackup": "Đăng nhập để sao lưu mã của bạn",
"singIn": "Đăng nhập",
"sigInBackupReminder": "Vui lòng xuất mã của bạn để đảm bảo rằng bạn có bản sao lưu có thể khôi phục.",
"offlineModeWarning": "Bạn đã chọn tiếp tục mà không sao lưu. Vui lòng sao lưu thủ công để đảm bảo mã của bạn được an toàn.",
"showLargeIcons": "Hiện biểu tượng lớn",
"offlineModeWarning": "Bạn đã chọn tiếp tục mà không cần sao lưu. Vui lòng sao lưu thủ công để đảm bảo mã của bạn được an toàn.",
"showLargeIcons": "Hiển thị biểu tượng lớn",
"compactMode": "Chế độ thu gọn",
"shouldHideCode": "Ẩn mã",
"doubleTapToViewHiddenCode": "Bạn có thể nhấn đúp vào một mục để xem mã",
"focusOnSearchBar": "Mở tìm kiếm khi khởi động ứng dụng",
"confirmUpdatingkey": "Bạn có chắc muốn cập nhật khóa bí mật không?",
"confirmUpdatingkey": "Bạn có chắc chắn muốn cập nhật khóa bí mật không?",
"minimizeAppOnCopy": "Thu nhỏ khi sao chép",
"editCodeAuthMessage": "Xác thực để sửa mã",
"deleteCodeAuthMessage": "Xác thực để xóa mã",
"showQRAuthMessage": "Xác thực để hiện mã QR",
"editCodeAuthMessage": "Xác minh để chỉnh sửa mã",
"deleteCodeAuthMessage": "Xác minh để xóa mã",
"showQRAuthMessage": "Xác minh để hiển thị mã QR",
"confirmAccountDeleteTitle": "Xác nhận xóa tài khoản",
"confirmAccountDeleteMessage": "Tài khoản này được liên kết với các ứng dụng Ente khác, nếu bạn có ng.\n\nDữ liệu bạn đã tải lên, trên tất cả ứng dụng Ente, sẽ được lên lịch để xóa, và tài khoản của bạn sẽ bị xóa vĩnh viễn.",
"androidBiometricHint": "Xác minh danh tính",
"confirmAccountDeleteMessage": "Tài khoản này được liên kết với các ứng dụng Ente trên các nền tảng khác, nếu bạn có sử dụng.\n\nDữ liệu đã tải lên của bạn, trên mọi nền tảng, sẽ bị lên lịch xóa và tài khoản của bạn sẽ bị xóa vĩnh viễn.",
"androidBiometricHint": "Xác định danh tính",
"@androidBiometricHint": {
"description": "Hint message advising the user how to authenticate with biometrics. It is used on Android side. Maximum 60 characters."
},
"androidBiometricNotRecognized": "Không nhận diện được. Thử lại.",
"androidBiometricNotRecognized": "Không nhận dạng được. Vui lòng thử lại.",
"@androidBiometricNotRecognized": {
"description": "Message to let the user know that authentication was failed. It is used on Android side. Maximum 60 characters."
},
@@ -414,19 +413,19 @@
"@androidDeviceCredentialsSetupDescription": {
"description": "Message advising the user to go to the settings and configure device credentials on their device. It shows in a dialog on Android side."
},
"goToSettings": "Đi đến cài đặt",
"goToSettings": "Chuyển đến cài đặt",
"@goToSettings": {
"description": "Message showed on a button that the user can click to go to settings pages from the current dialog. It is used on both Android and iOS side. Maximum 30 characters."
},
"androidGoToSettingsDescription": "Xác thực sinh trắc học chưa được thiết lập trên thiết bị của bạn. Đi đến 'Cài đặt > Bảo mật' để thêm xác thực sinh trắc học.",
"androidGoToSettingsDescription": "Xác thực sinh trắc học chưa được thiết lập trên thiết bị của bạn. Đi tới 'Cài đặt > Bảo mật' để thêm xác thực sinh trắc học.",
"@androidGoToSettingsDescription": {
"description": "Message advising the user to go to the settings and configure biometric on their device. It shows in a dialog on Android side."
},
"iOSLockOut": "Xác thực sinh trắc học đã bị vô hiệu hóa. Vui lòng khóa và mở khóa màn hình của bạn để kích hoạt lại.",
"iOSLockOut": "Xác thực sinh trắc học bị vô hiệu hóa. Vui lòng khóa và mở khóa màn hình của bạn để kích hoạt .",
"@iOSLockOut": {
"description": "Message advising the user to re-enable biometrics on their device. It shows in a dialog on iOS side."
},
"iOSGoToSettingsDescription": "Xác thực sinh trắc học chưa được thiết lập trên thiết bị của bạn. Vui lòng kích hoạt Touch ID hoặc Face ID.",
"iOSGoToSettingsDescription": "Xác thực sinh trắc học chưa được thiết lập trên thiết bị của bạn. Vui lòng bật Touch ID hoặc Face ID trên điện thoại của bạn.",
"@iOSGoToSettingsDescription": {
"description": "Message advising the user to go to the settings and configure Biometrics for their device. It shows in a dialog on iOS side."
},
@@ -437,25 +436,25 @@
"noInternetConnection": "Không có kết nối Internet",
"pleaseCheckYourInternetConnectionAndTryAgain": "Vui lòng kiểm tra kết nối internet của bạn và thử lại.",
"signOutFromOtherDevices": "Đăng xuất khỏi các thiết bị khác",
"signOutOtherBody": "Nếu bạn nghĩ rằng ai đó biết mật khẩu của bạn, hãy ép tài khoản của bạn đăng xuất khỏi tất cả thiết bị khác đang sử dụng.",
"signOutOtherBody": "Nếu bạn cho rằng ai đó có thể biết mật khẩu của mình, bạn có thể buộc đăng xuất tất cả các thiết bị khác đang sử dụng tài khoản của mình.",
"signOutOtherDevices": "Đăng xuất khỏi các thiết bị khác",
"doNotSignOut": "Không đăng xuất",
"hearUsWhereTitle": "Bạn biết Ente từ đâu? (tùy chọn)",
"hearUsExplanation": "Chúng tôi không theo dõi cài đặt ứng dụng, nên nếu bạn bật mí bạn tìm thấy chúng tôi từ đâu sẽ rất hữu ích!",
"recoveryKeySaved": "Đã lưu mã khôi phục vào thư mục Tải xuống!",
"doNotSignOut": "Không được đăng xuất",
"hearUsWhereTitle": "Bạn biết đến Ente bằng cách nào? (không bắt buộc)",
"hearUsExplanation": "Chúng tôi không theo dõi lượt cài đặt ứng dụng. Sẽ rất hữu ích nếu bạn cho chúng tôi biết nơi bạn tìm thấy chúng tôi!",
"recoveryKeySaved": "Đã lưu khoá dự phòng vào thư mục Tải về!",
"waitingForBrowserRequest": "Đang chờ yêu cầu từ trình duyệt...",
"waitingForVerification": "Đang chờ xác minh...",
"passkey": "Khóa truy cập",
"passKeyPendingVerification": "Xác minh vẫn đang chờ",
"loginSessionExpired": "Phiên đăng nhập đã hết hạn",
"loginSessionExpiredDetails": "Phiên đăng nhập của bạn đã hết hạn. Vui lòng đăng nhập lại.",
"developerSettingsWarning": "Bạn có chắc muốn thay đổi cài đặt Nhà phát triển không?",
"developerSettings": "Cài đặt Nhà phát triển",
"waitingForVerification": "Đang chờ xác thực",
"passkey": "Mã khoá",
"passKeyPendingVerification": "Đang chờ xác thực",
"loginSessionExpired": "Phiên làm việc hết hạn",
"loginSessionExpiredDetails": "Phiên làm việc hết hạn. Vui lòng đăng nhập lại.",
"developerSettingsWarning": "Bạn có chắc chắn muốn thay đổi Tuỳ chọn cho nhà phát triển không?",
"developerSettings": "Cài đặt cho nhà phát triển",
"serverEndpoint": "Điểm cuối máy chủ",
"invalidEndpoint": "Điểm cuối không hợp lệ",
"invalidEndpointMessage": "Xin lỗi, điểm cuối bạn nhập không hợp lệ. Vui lòng nhập một điểm cuối hợp lệ và thử lại.",
"endpointUpdatedMessage": "Điểm cuối đã được cập nhật thành công",
"customEndpoint": "Đã kết nối với {endpoint}",
"endpointUpdatedMessage": "Cập nhật điểm cuối thành công",
"customEndpoint": "Đã kết nối đến",
"pinText": "Ghim",
"unpinText": "Bỏ ghim",
"pinnedCodeMessage": "{code} đã được ghim",
@@ -467,37 +466,37 @@
"create": "Tạo",
"editTag": "Sửa thẻ",
"deleteTagTitle": "Xóa thẻ?",
"deleteTagMessage": "Bạn có chắc muốn xóa thẻ này không? Hành động này không thể hoàn tác.",
"deleteTagMessage": "Bạn có chắc chắn muốn xóa thẻ này không? Hành động này không thể đảo ngược.",
"somethingWentWrongParsingCode": "Chúng tôi không thể phân tích {x} mã.",
"updateNotAvailable": "Cập nhật không khả dụng",
"viewRawCodes": "Xem mã thô",
"rawCodes": "Mã thô",
"rawCodeData": "Dữ liệu thô",
"viewRawCodes": "Xem mã nguồn",
"rawCodes": "Mã nguồn",
"rawCodeData": "Dữ liệu thô",
"appLock": "Khóa ứng dụng",
"noSystemLockFound": "Không tìm thấy khóa hệ thống",
"toEnableAppLockPleaseSetupDevicePasscodeOrScreen": "Để bật khóa ứng dụng, vui lòng thiết lập mã khóa thiết bị hoặc khóa màn hình trong cài đặt hệ thống của bạn.",
"noSystemLockFound": "Không thấy kh hệ thống",
"toEnableAppLockPleaseSetupDevicePasscodeOrScreen": "Để bật kh ứng dụng, vui lòng thiết lập mật khẩu thiết bị hoặc khóa màn hình trong cài đặt hệ thống của bạn.",
"autoLock": "Tự động khóa",
"immediately": "Lập tức",
"immediately": "Tức thì",
"reEnterPassword": "Nhập lại mật khẩu",
"reEnterPin": "Nhập lại PIN",
"next": "Kế tiếp",
"tooManyIncorrectAttempts": "Thử sai nhiều lần",
"reEnterPin": "Nhập lại PIN",
"next": "Tiếp theo",
"tooManyIncorrectAttempts": "Quá nhiều lần thử không chính xác",
"tapToUnlock": "Nhấn để mở khóa",
"setNewPassword": "Đặt mật khẩu mới",
"setNewPassword": "Đặt lại mật khẩu",
"deviceLock": "Khóa thiết bị",
"hideContent": "Ẩn nội dung",
"hideContentDescriptionAndroid": "Ẩn nội dung khi chuyển ứng dụng và chặn chụp màn hình",
"hideContentDescriptioniOS": "Ẩn nội dung ứng dụng trong trình chuyển đổi ứng dụng",
"autoLockFeatureDescription": "Sau thời gian này, ứng dụng sẽ khóa sau khi được chạy ở chế độ nền",
"appLockDescription": "Chọn giữa màn hình khóa mặc định của thiết bị và màn hình khóa tùy chỉnh với PIN hoặc mật khẩu.",
"pinLock": "Khóa PIN",
"enterPin": "Nhập PIN",
"setNewPin": "Đặt PIN mới",
"importFailureDescNew": "Không thể phân tích tệp đã chọn.",
"hideContentDescriptioniOS": "Ẩn nội dung khi chuyển ứng dụng",
"autoLockFeatureDescription": "Thời gian ứng dụng tự kh sau khi ở trạng thái nền",
"appLockDescription": "Chọn giữa màn hình kh mặc định của thiết bị và màn hình khoá tự chọn dùng mã PIN hoặc mật khẩu.",
"pinLock": " PIN",
"enterPin": "Nhập PIN",
"setNewPin": "Đổi mã PIN",
"importFailureDescNew": "Không thể phân tích file đã chọn.",
"appLockNotEnabled": "Khóa ứng dụng chưa được bật",
"appLockNotEnabledDescription": "Vui lòng bật khóa ứng dụng từ Bảo mật > Khóa ứng dụng",
"authToViewPasskey": "Vui lòng xác thực để xem mã truy cập",
"appLockOfflineModeWarning": "Bạn đã chọn tiếp tục mà không sao lưu. Nếu bạn quên khóa ứng dụng, bạn sẽ không thể truy cập dữ liệu của mình.",
"authToViewPasskey": "Vui lòng xác thực để xem mã khóa",
"appLockOfflineModeWarning": "Bạn đã chọn tiếp tục mà không có bản sao lưu. Nếu bạn quên khóa ứng dụng, bạn sẽ bị khóa khỏi việc truy cập dữ liệu của mình.",
"duplicateCodes": "Mã trùng lặp",
"noDuplicates": "✨ Không có trùng lặp",
"youveNoDuplicateCodesThatCanBeCleared": "Bạn không có mã nào bị trùng để xóa",
@@ -506,18 +505,13 @@
"selectAll": "Chọn tất cả",
"deleteDuplicates": "Xóa trùng lặp",
"plainHTML": "HTML thuần",
"tellUsWhatYouThink": "Cho biết bạn nghĩ gì",
"tellUsWhatYouThink": "Hãy cho chúng tôi biết bạn nghĩ gì",
"dropReviewiOS": "Đánh giá ngay trên App Store",
"dropReviewAndroid": "Đánh giá ngay trên Play Store",
"supportEnte": "Hỗ trợ <bold-green>ente</bold-green>",
"giveUsAStarOnGithub": "Tặng sao trên GitHub",
"free5GB": "Miễn phí 5GB cho <bold-green>ente</bold-green> Photos",
"giveUsAStarOnGithub": "Cho chúng tôi ngôi sao trên Github",
"free5GB": "Miễn phí 5GB cho <bold-green>ente</bold-green> Hình ảnh",
"loginWithAuthAccount": "Đăng nhập bằng tài khoản Ente Auth",
"freeStorageOffer": "Giảm giá 10% cho <bold-green>ente</bold-green> Photos",
"freeStorageOfferDescription": "Dùng mã \"AUTH\" để được giảm 10% trong năm đầu tiên",
"advanced": "Nâng cao",
"algorithm": "Thuật toán",
"type": "Loại",
"period": "Thời hạn",
"digits": "Chữ số"
"freeStorageOffer": "Giảm giá 10% cho <bold-green>ente</bold-green> Hình ảnh",
"freeStorageOfferDescription": "Sử dụng mã giảm giá \"AUTH\" để được giảm 10% trong năm đầu tiên"
}

View File

@@ -18,8 +18,6 @@
</screenshot>
</screenshots>
<releases>
<release version="4.4.3" date="2025-06-21" />
<release version="4.4.2" date="2025-06-21" />
<release version="4.4.0" date="2025-05-31" />
<release version="4.3.8" date="2025-05-20" />
<release version="4.2.4" date="2025-01-11" />

View File

@@ -1,7 +1,7 @@
name: ente_auth
description: ente two-factor authenticator
version: 4.4.3+443
version: 4.4.1+441
publish_to: none
environment:

View File

@@ -46,7 +46,7 @@ You can alternatively install the build from PlayStore or F-Droid.
## 🧑‍💻 Building from source
1. [Install Flutter v3.27.4](https://flutter.dev/docs/get-started/install).
1. [Install Flutter v3.24.3](https://flutter.dev/docs/get-started/install).
2. Pull in all submodules with `git submodule update --init --recursive`

Some files were not shown because too many files have changed in this diff Show More