mirror of
https://github.com/skoobasteeve/skoobasteeve.github.io.2.git
synced 2026-03-20 07:58:57 +00:00
Compare commits
31 Commits
form-test
...
e7269c40cd
| Author | SHA1 | Date | |
|---|---|---|---|
|
e7269c40cd
|
|||
|
73f02fc964
|
|||
|
cbe5b72833
|
|||
|
4db791aa02
|
|||
|
|
073651bb8a | ||
|
1b7861fcba
|
|||
|
7057e88bc3
|
|||
|
ce142465b8
|
|||
|
535c4b2ddb
|
|||
|
a240d00ad1
|
|||
| 7d043d1901 | |||
|
|
82f2e1c604 | ||
| e1220573a3 | |||
| 12923178e4 | |||
| 0603df625a | |||
| ec236d164d | |||
| 12da493d02 | |||
| 09555857a5 | |||
| 0b1b837a3a | |||
| a1009ba693 | |||
| a0741b118c | |||
| c4c031e396 | |||
| b81af5bdfc | |||
| 01c85f968e | |||
| f73e2e7cc2 | |||
|
|
330f65b394 | ||
| f7828305ee | |||
| f639d251b3 | |||
| 8dc7d17015 | |||
| fe6991fb0b | |||
| 0349db6717 |
16
.devcontainer/devcontainer.json
Normal file
16
.devcontainer/devcontainer.json
Normal file
@@ -0,0 +1,16 @@
|
||||
{
|
||||
"image": "mcr.microsoft.com/devcontainers/jekyll:bookworm",
|
||||
|
||||
"customizations": {
|
||||
"vscode": {
|
||||
"extensions": [
|
||||
"albert.TabOut",
|
||||
"ecmel.vscode-html-css",
|
||||
"redhat.vscode-yaml",
|
||||
"rebornix.Ruby"
|
||||
]
|
||||
}
|
||||
},
|
||||
|
||||
"forwardPorts": [4000]
|
||||
}
|
||||
2
404.html
2
404.html
@@ -20,6 +20,6 @@ layout: default
|
||||
<div class="container">
|
||||
<h1>404</h1>
|
||||
|
||||
<p><strong>Page not found :(</strong></p>
|
||||
<p><strong>Page not found</strong></p>
|
||||
<p>The requested page could not be found.</p>
|
||||
</div>
|
||||
|
||||
2
Gemfile
2
Gemfile
@@ -15,6 +15,8 @@ source "https://rubygems.org"
|
||||
|
||||
gem "jekyll"
|
||||
gem "minimal-mistakes-jekyll"
|
||||
gem "jekyll-sitemap"
|
||||
gem "webrick"
|
||||
|
||||
# The following plugins are automatically loaded by the theme-gem:
|
||||
# gem "jekyll-paginate"
|
||||
|
||||
89
Gemfile.lock
89
Gemfile.lock
@@ -1,93 +1,100 @@
|
||||
GEM
|
||||
remote: https://rubygems.org/
|
||||
specs:
|
||||
addressable (2.7.0)
|
||||
public_suffix (>= 2.0.2, < 5.0)
|
||||
addressable (2.8.5)
|
||||
public_suffix (>= 2.0.2, < 6.0)
|
||||
colorator (1.1.0)
|
||||
concurrent-ruby (1.1.7)
|
||||
em-websocket (0.5.2)
|
||||
concurrent-ruby (1.2.2)
|
||||
em-websocket (0.5.3)
|
||||
eventmachine (>= 0.12.9)
|
||||
http_parser.rb (~> 0.6.0)
|
||||
http_parser.rb (~> 0)
|
||||
eventmachine (1.2.7)
|
||||
faraday (1.0.1)
|
||||
multipart-post (>= 1.2, < 3)
|
||||
ffi (1.13.1)
|
||||
faraday (2.7.10)
|
||||
faraday-net_http (>= 2.0, < 3.1)
|
||||
ruby2_keywords (>= 0.0.4)
|
||||
faraday-net_http (3.0.2)
|
||||
ffi (1.15.5)
|
||||
forwardable-extended (2.6.0)
|
||||
http_parser.rb (0.6.0)
|
||||
i18n (1.8.5)
|
||||
google-protobuf (3.24.0-x86_64-linux)
|
||||
http_parser.rb (0.8.0)
|
||||
i18n (1.14.1)
|
||||
concurrent-ruby (~> 1.0)
|
||||
jekyll (4.1.1)
|
||||
jekyll (4.3.2)
|
||||
addressable (~> 2.4)
|
||||
colorator (~> 1.0)
|
||||
em-websocket (~> 0.5)
|
||||
i18n (~> 1.0)
|
||||
jekyll-sass-converter (~> 2.0)
|
||||
jekyll-sass-converter (>= 2.0, < 4.0)
|
||||
jekyll-watch (~> 2.0)
|
||||
kramdown (~> 2.1)
|
||||
kramdown (~> 2.3, >= 2.3.1)
|
||||
kramdown-parser-gfm (~> 1.0)
|
||||
liquid (~> 4.0)
|
||||
mercenary (~> 0.4.0)
|
||||
mercenary (>= 0.3.6, < 0.5)
|
||||
pathutil (~> 0.9)
|
||||
rouge (~> 3.0)
|
||||
rouge (>= 3.0, < 5.0)
|
||||
safe_yaml (~> 1.0)
|
||||
terminal-table (~> 1.8)
|
||||
jekyll-feed (0.15.0)
|
||||
terminal-table (>= 1.8, < 4.0)
|
||||
webrick (~> 1.7)
|
||||
jekyll-feed (0.17.0)
|
||||
jekyll (>= 3.7, < 5.0)
|
||||
jekyll-gist (1.5.0)
|
||||
octokit (~> 4.2)
|
||||
jekyll-include-cache (0.2.0)
|
||||
jekyll-include-cache (0.2.1)
|
||||
jekyll (>= 3.7, < 5.0)
|
||||
jekyll-paginate (1.1.0)
|
||||
jekyll-sass-converter (2.1.0)
|
||||
sassc (> 2.0.1, < 3.0)
|
||||
jekyll-sass-converter (3.0.0)
|
||||
sass-embedded (~> 1.54)
|
||||
jekyll-sitemap (1.4.0)
|
||||
jekyll (>= 3.7, < 5.0)
|
||||
jekyll-watch (2.2.1)
|
||||
listen (~> 3.0)
|
||||
kramdown (2.3.0)
|
||||
kramdown (2.4.0)
|
||||
rexml
|
||||
kramdown-parser-gfm (1.1.0)
|
||||
kramdown (~> 2.0)
|
||||
liquid (4.0.3)
|
||||
listen (3.2.1)
|
||||
liquid (4.0.4)
|
||||
listen (3.8.0)
|
||||
rb-fsevent (~> 0.10, >= 0.10.3)
|
||||
rb-inotify (~> 0.9, >= 0.9.10)
|
||||
mercenary (0.4.0)
|
||||
minimal-mistakes-jekyll (4.20.2)
|
||||
minimal-mistakes-jekyll (4.24.0)
|
||||
jekyll (>= 3.7, < 5.0)
|
||||
jekyll-feed (~> 0.1)
|
||||
jekyll-gist (~> 1.5)
|
||||
jekyll-include-cache (~> 0.1)
|
||||
jekyll-paginate (~> 1.1)
|
||||
jekyll-sitemap (~> 1.3)
|
||||
multipart-post (2.1.1)
|
||||
octokit (4.18.0)
|
||||
faraday (>= 0.9)
|
||||
sawyer (~> 0.8.0, >= 0.5.3)
|
||||
octokit (4.25.1)
|
||||
faraday (>= 1, < 3)
|
||||
sawyer (~> 0.9)
|
||||
pathutil (0.16.2)
|
||||
forwardable-extended (~> 2.6)
|
||||
public_suffix (4.0.6)
|
||||
rb-fsevent (0.10.4)
|
||||
public_suffix (5.0.3)
|
||||
rb-fsevent (0.11.2)
|
||||
rb-inotify (0.10.1)
|
||||
ffi (~> 1.0)
|
||||
rexml (3.2.4)
|
||||
rouge (3.23.0)
|
||||
rexml (3.2.6)
|
||||
rouge (4.1.3)
|
||||
ruby2_keywords (0.0.5)
|
||||
safe_yaml (1.0.5)
|
||||
sassc (2.4.0)
|
||||
ffi (~> 1.9)
|
||||
sawyer (0.8.2)
|
||||
sass-embedded (1.64.2-x86_64-linux-gnu)
|
||||
google-protobuf (~> 3.23)
|
||||
sawyer (0.9.2)
|
||||
addressable (>= 2.3.5)
|
||||
faraday (> 0.8, < 2.0)
|
||||
terminal-table (1.8.0)
|
||||
unicode-display_width (~> 1.1, >= 1.1.1)
|
||||
unicode-display_width (1.7.0)
|
||||
faraday (>= 0.17.3, < 3)
|
||||
terminal-table (3.0.2)
|
||||
unicode-display_width (>= 1.1.1, < 3)
|
||||
unicode-display_width (2.4.2)
|
||||
webrick (1.8.1)
|
||||
|
||||
PLATFORMS
|
||||
ruby
|
||||
x86_64-linux
|
||||
|
||||
DEPENDENCIES
|
||||
jekyll
|
||||
jekyll-sitemap
|
||||
minimal-mistakes-jekyll
|
||||
webrick
|
||||
|
||||
BUNDLED WITH
|
||||
2.1.4
|
||||
2.4.18
|
||||
|
||||
20
_config.yml
20
_config.yml
@@ -96,23 +96,20 @@ author:
|
||||
email :
|
||||
links:
|
||||
- label: "E201 06CB 86FE 0B4D"
|
||||
icon: "fas fa-fingerprint"
|
||||
icon: "fas fa-fw fa-fingerprint"
|
||||
url: "https://keybase.io/scubasteve/pgp_keys.asc?fingerprint=2dc3a1066bba7040fe7963d9e20106cb86fe0b4d"
|
||||
- label: "Email"
|
||||
icon: "fas fa-fw fa-envelope-square"
|
||||
url: "mailto:ray@raylyon.net"
|
||||
- label: "Keybase"
|
||||
icon: "fab fa-keybase"
|
||||
icon: "fab fa-fw fa-keybase"
|
||||
url: "https://keybase.io/scubasteve"
|
||||
- label: "Website"
|
||||
icon: "fas fa-fw fa-link"
|
||||
# url: "https://your-website.com"
|
||||
- label: "Twitter"
|
||||
icon: "fab fa-fw fa-twitter-square"
|
||||
# url: "https://twitter.com/"
|
||||
- label: "Facebook"
|
||||
icon: "fab fa-fw fa-facebook-square"
|
||||
# url: "https://facebook.com/"
|
||||
- label: "Mastodon"
|
||||
icon: "fab fa-fw fa-mastodon"
|
||||
url: "https://fosstodon.org/@skoobasteeve"
|
||||
- label: "GitHub"
|
||||
icon: "fab fa-fw fa-github"
|
||||
url: "https://github.com/skoobasteeve"
|
||||
@@ -283,3 +280,10 @@ defaults:
|
||||
related: true
|
||||
classes: wide
|
||||
show_date: true
|
||||
# _pages
|
||||
- scope:
|
||||
path: ""
|
||||
type: pages
|
||||
values:
|
||||
layout: single
|
||||
author_profile: true
|
||||
|
||||
20
_includes/footer.html
Executable file
20
_includes/footer.html
Executable file
@@ -0,0 +1,20 @@
|
||||
<div class="page__footer-follow">
|
||||
<ul class="social-icons">
|
||||
{% if site.data.ui-text[site.locale].follow_label %}
|
||||
<li><strong>{{ site.data.ui-text[site.locale].follow_label }}</strong></li>
|
||||
{% endif %}
|
||||
|
||||
{% if site.footer.links %}
|
||||
{% for link in site.footer.links %}
|
||||
{% if link.label and link.url %}
|
||||
<li><a href="{{ link.url }}" rel="nofollow noopener noreferrer"><i class="{{ link.icon | default: 'fas fa-link' }}" aria-hidden="true"></i> {{ link.label }}</a></li>
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
{% endif %}
|
||||
|
||||
<li><a href="{% if site.atom_feed.path %}{{ site.atom_feed.path }}{% else %}{{ '/feed.xml' | relative_url }}{% endif %}"><i class="fas fa-fw fa-rss-square" aria-hidden="true"></i> {{ site.data.ui-text[site.locale].feed_label | default: "Feed" }}</a></li>
|
||||
<li><a rel="me" href="https://fosstodon.org/@skoobasteeve"><i class="fab fa-mastodon" aria-hidden="true"></i> Mastodon</a></li>
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
<div class="page__footer-copyright">© {{ site.time | date: '%Y' }} {{ site.name | default: site.title }}. {{ site.data.ui-text[site.locale].powered_by | default: "Powered by" }} <a href="https://jekyllrb.com" rel="nofollow">Jekyll</a> & <a href="https://mademistakes.com/work/minimal-mistakes-jekyll-theme/" rel="nofollow">Minimal Mistakes</a>.</div>
|
||||
@@ -8,6 +8,6 @@ I love Linux, open-source, and technology in general.
|
||||
|
||||
This blog was built using [Jekyll](https://jekyllrb.com/) and the [Minimal Mistakes](https://github.com/mmistakes/minimal-mistakes) theme. All updates and tweaks can be followed on by GitHub repo linked in the sidebar.
|
||||
|
||||
I'm not very active on social media, but feel free to email me or leave a comment if you want to get in touch. You'll likely receive a quick response as I jump on any opportunity to talk tech.
|
||||
I'm not very active on social media (besides <a rel="me" href="https://fosstodon.org/@skoobasteeve">Mastodon</a>), but feel free to email me or leave a comment if you want to get in touch. You'll likely receive a quick response as I jump on any opportunity to talk tech.
|
||||
|
||||
Thanks and Happy Hacking!
|
||||
@@ -1,7 +1,8 @@
|
||||
---
|
||||
layout: single
|
||||
title: "Painless On-Demand NAS Connections in Linux with Systemd Automount"
|
||||
title: "On-Demand NFS and Samba Connections in Linux with Systemd Automount"
|
||||
date: 2020-10-07 19:00:00
|
||||
last_modified_at: 2021-08-26
|
||||
categories: [Linux Administration]
|
||||
tags: linux samba nas systemd ubuntu
|
||||
comments: true
|
||||
@@ -21,7 +22,7 @@ If you're not familiar with Systemd unit files and how they work, I would highly
|
||||
|
||||
You'll need to create dedicated folders on your machine where the shares will be mounted.
|
||||
|
||||
``` bash
|
||||
```bash
|
||||
$ sudo mkdir -p /mnt/smb/sambashare
|
||||
$ sudo mkdir -p /mnt/nfs/nfsshare
|
||||
```
|
||||
@@ -30,7 +31,7 @@ $ sudo mkdir -p /mnt/nfs/nfsshare
|
||||
|
||||
If your Samba server uses authentication, you'll need to create a file with your login details that Systemd can use to connect. These should be saved in a safe location with restricted permissions.
|
||||
|
||||
``` bash
|
||||
```bash
|
||||
$ sudo nano /etc/samba/smbcreds
|
||||
```
|
||||
|
||||
@@ -39,7 +40,7 @@ username=[USERNAME]
|
||||
password=[PASSWORD]
|
||||
```
|
||||
|
||||
``` bash
|
||||
```bash
|
||||
$ sudo chmod 600 /etc/samba/smbcreds
|
||||
```
|
||||
|
||||
@@ -47,13 +48,13 @@ $ sudo chmod 600 /etc/samba/smbcreds
|
||||
|
||||
#### Samba
|
||||
|
||||
``` bash
|
||||
```bash
|
||||
$ sudo apt install samba cifs-utils
|
||||
```
|
||||
|
||||
#### NFS
|
||||
|
||||
``` bash
|
||||
```bash
|
||||
$ sudo apt install nfs-common
|
||||
```
|
||||
|
||||
@@ -63,7 +64,7 @@ To make this work, we need (2) unit files for each connection: the **mount** uni
|
||||
|
||||
The below instructions assume your samba share is located at `//example.server/sambafiles`.
|
||||
|
||||
``` bash
|
||||
```bash
|
||||
$ sudo nano /etc/systemd/system/mnt-smb-sambashare.mount
|
||||
```
|
||||
|
||||
@@ -86,20 +87,22 @@ WantedBy=multi-user.target
|
||||
```
|
||||
|
||||
A few notes on the above file:
|
||||
|
||||
* `vers=2.1` - adjust this based on the version of samba running on your server
|
||||
* `uid=1000` - adjust this based on your local user ID to avoid permissions problems. This is usually 1000 on a desktop system.
|
||||
|
||||
\
|
||||
Next we need to create the automount file in the same location.
|
||||
|
||||
``` bash
|
||||
***EDIT 2021-08-26*** Reader flansuse pointed out that including `Requires=network-online.target` in the automount file did not conform with systemd guidelines. I confirmed that the mounts work perfectly well without that line, so it's been removed.
|
||||
|
||||
```bash
|
||||
$ sudo nano /etc/systemd/system/mnt-smb-sambashare.automount
|
||||
```
|
||||
|
||||
```
|
||||
[Unit]
|
||||
Description=samba automount for yourfiles
|
||||
Requires=network-online.target
|
||||
|
||||
[Automount]
|
||||
Where=/mnt/smb/sambashare
|
||||
@@ -113,8 +116,10 @@ WantedBy=multi-user.target
|
||||
|
||||
The below instructions assume your NFS share is located at `example.server:/srv/nfsfiles`.
|
||||
|
||||
``` bash
|
||||
$ sudo nano /etc/systemd/system/mnt-nfs-nfssahre.mount
|
||||
***EDIT 2021-08-26*** Reader Denis suggested adding the `TimeoutSec` parameter to the below file to prevent lock-ups when the share isn't present on your local network. Thank you Denis for the contribution!
|
||||
|
||||
```bash
|
||||
$ sudo nano /etc/systemd/system/mnt-nfs-nfsshare.mount
|
||||
```
|
||||
|
||||
```
|
||||
@@ -126,6 +131,7 @@ What=example.server:/srv/nfsfiles
|
||||
Where=/mnt/nfs/nfsshare
|
||||
Type=nfs
|
||||
Options=defaults
|
||||
TimeoutSec=5
|
||||
|
||||
[Install]
|
||||
WantedBy=multi-user.target
|
||||
@@ -134,14 +140,13 @@ WantedBy=multi-user.target
|
||||
\
|
||||
Same as before, we need to create the automount file in the same location.
|
||||
|
||||
``` bash
|
||||
$ sudo nano /etc/systemd/system/mnt-smb-nfsshare.automount
|
||||
```bash
|
||||
$ sudo nano /etc/systemd/system/mnt-nfs-nfsshare.automount
|
||||
```
|
||||
|
||||
```
|
||||
[Unit]
|
||||
Description=nfs automount for nfsfiles
|
||||
Requires=network-online.target
|
||||
|
||||
[Automount]
|
||||
Where=/mnt/nfs/nfsshare
|
||||
|
||||
284
_posts/2020-10-23-nextcloud-photos.md
Normal file
284
_posts/2020-10-23-nextcloud-photos.md
Normal file
@@ -0,0 +1,284 @@
|
||||
---
|
||||
layout: single
|
||||
title: "Better Nextcloud Photo Albums with Preview Generator and Exiftool"
|
||||
date: 2020-10-27 18:00:00
|
||||
excerpt: "If you host and use a Nextcloud server, you know that it's good at many things. Unfortunately, displaying photos is not one of them."
|
||||
categories: [Linux Administration]
|
||||
tags: linux ubuntu nextcloud photos exiftool
|
||||
comments: true
|
||||
---
|
||||
|
||||
{:class="img-responsive" .align-center}
|
||||
|
||||
If you host and use a Nextcloud server, you know that it's good at many things. Unfortunately, displaying photos is not one of them. Since Nextcloud does not read photo metadata, your albums will often appear out-of-order. You may also notice that thumbnails and previews take a very long time to load and flipping quickly through a bunch of photos becomes a painful waiting game.
|
||||
|
||||
The good news is that because Nextcloud is a wonderful piece of FOSS that we're self-hosting, we can make some modifications to smooth out these pain points.
|
||||
|
||||
There are (2) pieces of software we'll be using to accomplish this:
|
||||
|
||||
- [Preview Generator](https://apps.nextcloud.com/apps/previewgenerator) (Nextcloud app)
|
||||
- [exiftool](https://exiftool.org/) (Linux app)
|
||||
|
||||
Both are freely available from Nextcloud and your distro's package manager, respectively. Let's dive in!
|
||||
|
||||
# Previews and Thumbnails
|
||||
|
||||
First we need to fix Nextcloud's preview generation. By default, Nextcloud generates photo previews and thumbnails on-demand, leading to slow load times. To fix this, we're going to use the Preview Generator app for Nextcloud to pre-generate previews on a regular basis. That way, your photos are ready to view as soon as you open the folder.
|
||||
|
||||
1. **Install the Preview Generator app for Nextcloud**. From a Nextcloud account with admin permissions, navigate to the Apps section and locate Preview Generator under the Multimedia category. Click Download and enable.
|
||||
|
||||
{:class="img-responsive" .align-center}
|
||||
|
||||
2. **Configure preview and thumbnail settings.** While the default settings work well from a performance standpoint, they cause Nextcloud to generate a huge number of previews and thumbnails for each photo. Once you add a lot of photos, you'll notice that these previews eat into your storage significantly (sometimes more than the photos themselves). Fortunately, Preview Generator is highly configurable.
|
||||
|
||||
SSH into your Nextcloud server and follow the instructions below.
|
||||
|
||||
**Note:** I've found that the below settings provide a good balance of resolution, performance, and storage usage for my environment. You can tweak them depending on your needs.
|
||||
|
||||
Set the default thumbnail sizes by using the following occ commands:
|
||||
|
||||
```bash
|
||||
sudo -u www-data php /var/www/nextcloud/occ config:app:set --value="32 256" previewgenerator squareSizes
|
||||
sudo -u www-data php /var/www/nextcloud/occ config:app:set --value="256 384" previewgenerator widthSizes
|
||||
sudo -u www-data php /var/www/nextcloud/occ config:app:set --value="256" previewgenerator heightSizes
|
||||
```
|
||||
|
||||
Next, edit your config.php to specify the maximum preview size for images. This is going to effect the appearance and load time of images when you click on them.
|
||||
|
||||
```bash
|
||||
sudo nano /var/www/nextcloud/config/config.php
|
||||
```
|
||||
|
||||
Find the below lines toward the end of the file. If they don't exist, add them to the block.
|
||||
|
||||
```php
|
||||
'preview_max_x' => '2048',
|
||||
'preview_max_y' => '2048',
|
||||
'jpeg_quality' => '60',
|
||||
```
|
||||
|
||||
Save the file and restart the web server.
|
||||
|
||||
```bash
|
||||
sudo service apache2 restart
|
||||
```
|
||||
|
||||
3. **Generate initial previews.** Open a terminal on your Nextcloud server and run the following command:
|
||||
|
||||
```bash
|
||||
sudo -u www-data php /var/www/nextcloud/occ preview:generate-all -vvv
|
||||
```
|
||||
|
||||
The above command is run as the web server user since they are typically the owner of the Nextcloud directory, though you may need to tweak it based on your server configuration.
|
||||
|
||||
**NOTE:** Depending on the amount of photos you have, this could take a while to complete and use a high amount of resources. If you have users beyond yourself, it's probably best to run it during a low-activity period.
|
||||
|
||||
4. **Add a cron job.** This allows Preview Generator to run continuously generate previews as new photos are added to Nextcloud. To avoid permissions problems, we'll edit the crontab of the web server user:
|
||||
|
||||
```bash
|
||||
sudo -u www-data crontab -e
|
||||
```
|
||||
|
||||
Add the following below line to the file. The below example runs the command every 10 minutes, but you can set the frequency to whatever you want.
|
||||
|
||||
```bash
|
||||
*/10 * * * * /usr/bin/php -f /var/www/nextcloud/occ preview:pre-generate
|
||||
```
|
||||
|
||||
**NOTE:** If you have a specific version of PHP installed beyond your distro's default, you'll want to specify that version of the binary above (e.g. `php7.4` instead of `php`).
|
||||
|
||||
# Photo Sorting
|
||||
|
||||
**UPDATE 2021-01-26:** Added methods to run the script on both client and server systems.
|
||||
{: .notice--info}
|
||||
|
||||
Nextcloud is first and foremost a file sharing application, so it views files just as your file system would. This is great until you get to photo albums, where the EXIF metadata of the photo is more relevant to sorting than the filename or modified date. To be sure that all photos in Nextcloud display in chronological order, we need to get creative.
|
||||
|
||||
That's where the wonderful exiftool comes in. This powerful command-line application allows you to read and manipulate the EXIF data of a photo. The feature that solves our problem is the ability to read the original capture date of a photo and apply it to both the *last modified* attribute and the *filename*. This way, no matter how you sort the images in Nextcloud, they'll display in **chronological** order.
|
||||
|
||||
You have **two options** for using exiftool:
|
||||
|
||||
1. Run a script from a synced **client** computer.
|
||||
|
||||
2. Run a script on the data directory on the **server**.
|
||||
|
||||
The advantage of running it on the server is that you can automate periodic scans of your photos so they are always sorted properly and up-to-date. The disadvantage is that there are some extra steps involved that may take a long time depending on the speed of your server.
|
||||
|
||||
To get started using exiftool, follow the instructions below on one of your **Nextcloud clients.**
|
||||
|
||||
### Write the script
|
||||
|
||||
1. Install exiftool on your chosen Nextcloud client.
|
||||
|
||||
```bash
|
||||
sudo apt install exiftool
|
||||
```
|
||||
|
||||
2. Create a new file with the below contents and save it as a script.
|
||||
|
||||
```shell
|
||||
sudo nano photo-cleanup.sh
|
||||
```
|
||||
|
||||
**Option 1: Client Script:**
|
||||
|
||||
```shell
|
||||
#!/bin/sh
|
||||
|
||||
albumdir=$1
|
||||
|
||||
# use below variables if running on the server
|
||||
# nextclouddir="/var/www/nextcloud"
|
||||
# user who owns the photos
|
||||
# nextclouduser=""
|
||||
|
||||
echo "Changing modified date to shot date..."
|
||||
exiftool "-filemodifydate<datetimeoriginal" -r "$albumdir"
|
||||
|
||||
echo "Renaming files to shot date..."
|
||||
exiftool '-FileName<DateTimeOriginal' -r -d "%Y-%m-%d_%H.%M.%S%%-c.%%e" "$albumdir"
|
||||
|
||||
# uncomment the below command if running on the server
|
||||
# echo "Re-scanning your Nextcloud data directory..."
|
||||
# sudo -u www-data php "$nextclouddir"/occ files:scan "$nextclouduser"
|
||||
|
||||
exit 0
|
||||
```
|
||||
|
||||
**Option 2: Server Script:**
|
||||
|
||||
```shell
|
||||
#!/bin/sh
|
||||
|
||||
albumdir=$1
|
||||
|
||||
# use below variables if running on the server
|
||||
nextclouddir="/var/www/nextcloud"
|
||||
# user who owns the photos
|
||||
nextclouduser=""
|
||||
|
||||
echo "Changing modified date to shot date..."
|
||||
exiftool "-filemodifydate<datetimeoriginal" -r "$albumdir"
|
||||
|
||||
echo "Renaming files to shot date..."
|
||||
exiftool '-FileName<DateTimeOriginal' -r -d "%Y-%m-%d_%H.%M.%S%%-c.%%e" "$albumdir"
|
||||
|
||||
# uncomment the below command if running on the server
|
||||
echo "Re-scanning your Nextcloud data directory..."
|
||||
sudo -u www-data php "$nextclouddir"/occ files:scan "$nextclouduser"
|
||||
|
||||
exit 0
|
||||
```
|
||||
|
||||
I'll break down what's happening above:
|
||||
|
||||
```shell
|
||||
albumdir=$1
|
||||
```
|
||||
|
||||
Sets your album directory as the first argument when you execute the script.
|
||||
|
||||
```shell
|
||||
nextclouddir="/var/www/nextcloud"
|
||||
```
|
||||
|
||||
**Server script only**: set to your Nextcloud install folder.
|
||||
|
||||
```shell
|
||||
nextclouduser=""
|
||||
```
|
||||
|
||||
**Server script only**: set to the Nextcloud user that owns the photo directory.
|
||||
|
||||
```shell
|
||||
exiftool "-filemodifydate<datetimeoriginal" -r "$albumdir"
|
||||
```
|
||||
|
||||
Instructs exiftool to read `datetimeoriginal` (date and time the photo was shot) from each photo and apply it as the `filemodifydate`. The `-r` flag runs the command recursively so it will work its way through all folders in the photos directory.
|
||||
|
||||
```shell
|
||||
exiftool '-FileName<DateTimeOriginal' -r -d "%Y-%m-%d_%H.%M.%S%%-c.%%e" "$albumdir"
|
||||
```
|
||||
|
||||
Similar to the previous command but applies `datetimeoriginal` to the filename. The `-d` flag specifies how the date and time data are laid out in the new filename.
|
||||
|
||||
### Test the script
|
||||
|
||||
**Warning:** If you're choosing to run the **server** script, keep in mind that the final files:scan command can take a long time to complete depending on the amount of photos and speed of your instance. It's best to run it during a scheduled maintenance window.
|
||||
{: .notice--warning}
|
||||
|
||||
Let's test this simple script on a directory of photos.
|
||||
|
||||
Give the script permission to execute.
|
||||
|
||||
```shell
|
||||
chmod +x photo-cleanup.sh
|
||||
```
|
||||
|
||||
You can see below a directory filled with photos. Note the modify dates and filenames on the right side.
|
||||
|
||||
```shell
|
||||
ls -al Photos
|
||||
total 35340
|
||||
drwxrwxr-x 2 raylyon raylyon 4096 Aug 6 18:49 .
|
||||
drwxr-xr-x 6 raylyon raylyon 4096 Oct 25 21:51 ..
|
||||
-rwxr-xr-x 1 raylyon raylyon 6280032 Oct 19 01:42 P1060462.jpg
|
||||
-rwxr-xr-x 1 raylyon raylyon 4056662 Oct 19 02:02 P1060468.jpg
|
||||
-rwxr-xr-x 1 raylyon raylyon 4915105 Oct 19 02:05 P1060481.jpg
|
||||
-rwxr-xr-x 1 raylyon raylyon 6375408 Oct 19 02:06 P1060530.jpg
|
||||
-rwxr-xr-x 1 raylyon raylyon 6635572 Oct 19 02:06 P1060546.jpg
|
||||
-rwxr-xr-x 1 raylyon raylyon 7903375 Oct 19 02:08 P1060552.jpg
|
||||
```
|
||||
|
||||
Now we'll run the script on this directory.
|
||||
|
||||
```shell
|
||||
./photo-cleanup.sh "/home/raylyon/Nextcloud/Photos"
|
||||
Changing modified date to shot date...
|
||||
1 directories scanned
|
||||
6 image files updated
|
||||
Renaming files to shot date...
|
||||
1 directories scanned
|
||||
6 image files updated
|
||||
```
|
||||
|
||||
```shell
|
||||
ls -al Photos
|
||||
total 35340
|
||||
drwxrwxr-x 2 raylyon raylyon 4096 Oct 25 21:56 .
|
||||
drwxr-xr-x 6 raylyon raylyon 4096 Oct 25 21:51 ..
|
||||
-rwxr-xr-x 1 raylyon raylyon 6280032 Jul 31 11:27 2020-07-31_11.27.39.jpg
|
||||
-rwxr-xr-x 1 raylyon raylyon 4056662 Jul 31 12:09 2020-07-31_12.09.05.jpg
|
||||
-rwxr-xr-x 1 raylyon raylyon 4915105 Jul 31 12:35 2020-07-31_12.35.29.jpg
|
||||
-rwxr-xr-x 1 raylyon raylyon 6375408 Aug 1 08:22 2020-08-01_08.22.03.jpg
|
||||
-rwxr-xr-x 1 raylyon raylyon 6635572 Aug 1 19:46 2020-08-01_19.46.18.jpg
|
||||
-rwxr-xr-x 1 raylyon raylyon 7903375 Aug 1 19:47 2020-08-01_19.47.24.jpg
|
||||
```
|
||||
|
||||
Just like that, our filenames and metadata are updated.
|
||||
|
||||
### (Optional) Add a Cron job
|
||||
|
||||
You could run the script manually each time you add photos, but who has time for that? If you're frequently adding new photos and directories, you can automate it.
|
||||
|
||||
To do so, we'll add an entry to the crontab on the client or server.
|
||||
|
||||
**Client (user crontab)**
|
||||
|
||||
```bash
|
||||
crontab -e
|
||||
```
|
||||
|
||||
**Server (system crontab)**
|
||||
|
||||
```shell
|
||||
sudo crontab -e
|
||||
```
|
||||
|
||||
```shell
|
||||
*/30 * * * * /path/to/your/script/photo-cleanup.sh "/path/to/Nextcloud/Photos"
|
||||
```
|
||||
|
||||
The above entry runs the script every 30 minutes, checking the directory and any sub-directories for new photos and updating them accordingly. Adjust the timing to your needs.
|
||||
|
||||
Have any great Nextcloud photo tips that I missed? Shoot me an email or leave a comment below. Thanks for reading and happy hacking!
|
||||
197
_posts/2021-01-10-backup-planning.md
Normal file
197
_posts/2021-01-10-backup-planning.md
Normal file
@@ -0,0 +1,197 @@
|
||||
---
|
||||
layout: single
|
||||
title: "Backups: Planning an Effective Strategy"
|
||||
date: 2021-01-10 18:10:00
|
||||
categories: [Linux Administration]
|
||||
tags: linux backups BorgBackup borg rsync nextcloud
|
||||
comments: true
|
||||
---
|
||||
|
||||
If you've ever asked a sysadmin or computer geek for advice, you've probably heard the universal refrain: "Always have a backup" or "RAID is not a backup" or my personal favorite "One is none" (referring to copies of your data).
|
||||
|
||||
While virtually everyone working in this space agrees on the above, you'll get wildly different answers to your next question: "How do I do it?"
|
||||
|
||||
The intention of this post is to cut through the noise and give you an understanding of the concepts you should be thinking about before committing to a particular technology or piece of software.
|
||||
|
||||
***NOTE*** - Due to the nature of this blog, most of the example applications I provide are FOSS and Linux-compatible, but you can apply the same concepts to other apps and operating systems.
|
||||
|
||||
## Break Your Data Into "Tiers"
|
||||
|
||||
Whether you're talking about a server or a desktop, it's a safe bet that not every file on your hard drive(s) holds equal importance. That is, there are some files you care about vastly more than others. When setting up a backup system, sorting these files by priority will save you time, money, and disk space down the road.
|
||||
|
||||
### Tier 1: Files you can't afford to lose
|
||||
|
||||
Family pictures, tax documents, home videos; things that aren't replaceable or would incur significant cost to replace, financial or otherwise. **These should exist in at least 3 places**.
|
||||
|
||||
### Tier 2: Files that you *can* replace, but don't want to
|
||||
|
||||
Music and movies, either ripped from physical media or "obtained" from elsewhere, are good contenders for this category. You may have spent hours meticulously cataloging your media collection, but those files can always be re-downloaded or ripped. **These should exist in at least 2 places**.
|
||||
|
||||
### Tier 3: Files that don't matter
|
||||
|
||||
Installed applications, games, operating system files, miscellaneous downloads, etc. Files in this category can be easily replaced with a simple re-install or are publicly available on the internet. It's not necessary to back up these files unless you've got extra terabytes burning a hole in your pocket.
|
||||
|
||||
## Choose a Strategy for Each Tier
|
||||
|
||||
There are a huge amount of software options for handling your backups, and the strengths and weaknesses of each primarily depend on the type of data your backing up. It's important to understand these characteristics and so you can apply them to your different data tiers.
|
||||
|
||||
### Cloud Sync Services
|
||||
|
||||
Services like Google Drive, Dropbox, or self-hosted [Nextcloud](https://nextcloud.com/) (my personal choice) use desktop and mobile applications to automatically sync your files between your devices and a centralized cloud server. Files that you save to a defined folder on your computer are instantly uploaded to the cloud and downloaded to the other devices. These files are accessible from anywhere via a web interface.
|
||||
|
||||
**Advantages**
|
||||
|
||||
+ **Easy to set up** - Pick a service, create an account, download the application and sync your files.
|
||||
|
||||
+ **Instant and automatic** - Backups occur whenever a file is added or changed. No need to schedule a backup ahead of time or manually press a button.
|
||||
|
||||
+ **Resilient** - The web applications almost always have a "trash bin" for deleted file recovery, version control for rollbacks, and server infrastructure that gets its own backups. The files also exist offline on your synced devices.
|
||||
|
||||
+ **Readily Available** - Your files are accessible from any computer anywhere in the world via a web browser, including your smartphone.
|
||||
|
||||
**Disadvantages**
|
||||
|
||||
- **Expensive for high volumes** - The free tiers of most sync services only give you around 5-15GB of storage, so for anything larger than that you'll have to pay for the additional storage.
|
||||
|
||||
- **Cumbersome for large files** - It's easy for the desktop apps to get bogged down with large files and slow down your computer, and once your get up into the hundreds of gigabytes, you could fill up the hard drives of all your devices pretty quickly. You'll also be severely limited by the slow upload speeds of most home broadband connections.
|
||||
|
||||
- **Reliance on third-party** - You have to trust that Google, Dropbox, or other services will respect your privacy and keep your files safe. **EXCEPTION:** [Self-hosted Nextcloud server.](https://docs.nextcloud.com/server/20/admin_manual/installation/)
|
||||
|
||||
**Best for**
|
||||
|
||||
- **Tier 1** - Documents take up very little space and upload quickly. Even a years worth of photos from your smartphone will only use a few GB in most cases.
|
||||
|
||||
- **Tier 2 (smaller files)** - Application config files or even mp3s if you have a small collection.
|
||||
|
||||
### Local File Sync
|
||||
|
||||
This is as simple as it gets: plug in a USB hard drive or connect to a network share and copy your files to it. While it's possible to accomplish this with a drag-and-drop, there are many great software tools that can help: [FreeFileSync,](https://freefilesync.org/) [DirSyncPro](https://www.dirsyncpro.org/), and [rsync](https://wiki.archlinux.org/index.php/rsync) are all great options for the desktop.
|
||||
|
||||
**Advantages**
|
||||
|
||||
- **SImple** - Does not require extensive knowledge to set up and understand what's happening, and files aren't hidden behind compression or custom folder structures. Great for people who want visual verification of a successful backup.
|
||||
|
||||
- **Fast** - A local USB3 or gigabit LAN connection is going be faster than your internet upload speed 9 times out of 10.
|
||||
|
||||
- **Cheap** - In the long run, local storage is always cheaper than cloud.
|
||||
|
||||
- **Offline and in your control** - No need to rely on any third-party service or server that may be untrustworthy.
|
||||
|
||||
**Disadvantages**
|
||||
|
||||
- **Not as resilient as other options** - File sync applications, while simple, don't always have more advanced features like versioning and verification, making it easier to run into problems without realizing it.
|
||||
|
||||
**Best for**
|
||||
|
||||
- **Tier 2** - Without the storage limitations of the cloud, it's great to use on all your files, no matter how large.
|
||||
|
||||
### Local Backups
|
||||
|
||||
What's the difference between local backup and local sync? It's largely semantics, but for the purposes of this post I'll make some distinctions. The file sync applications I mentioned above are great for just that: ensuring that a folder in one location is an exact copy of a folder in another location. This is great, but if you want to get *serious* about your backups, a more specialized application is what you want.
|
||||
|
||||
Backup applications like [BorgBackup](https://www.borgbackup.org/), [Duplicati](https://www.duplicati.com/), and [BackupPC](https://backuppc.github.io/backuppc/) can also back up to a USB HDD or network share, but they also provide features that make your backups more efficient and resilient: versioning, encryption, de-duplication, and compression to name a few.
|
||||
|
||||
**Advantages**
|
||||
|
||||
- **Secure** - Encryption allows you to protect your backups with a password.
|
||||
|
||||
- **Resilient** - Retention of multiple versions and built-in error checking lowers your chances of losing data significantly.
|
||||
|
||||
- **Cheap** - Same hardware requirements as local sync, and all the software examples I gave are free and open-source.
|
||||
|
||||
- **Offline and in your control** - No need to rely on any third-party service or server that may be untrustworthy.
|
||||
|
||||
**Disadvantages**
|
||||
|
||||
- **Complexity** - The additional features these apps offer can make them more difficult to set up, and the extra features mean the backups will be hidden by specialized file names and folder structures.
|
||||
|
||||
**Best for**
|
||||
|
||||
- **Tier 2** - Without the storage limitations of the cloud, it's great to use on all your files, no matter how large.
|
||||
|
||||
- **Tier 1** - Combine with a cloud option and you'll have hard time ever losing your data.
|
||||
|
||||
### Cloud Backups
|
||||
|
||||
We already established the cloud as a great option for your Tier 1 files, so what makes cloud backups different from cloud sync services? Cloud backup applications use the same methodology as the local backup applications I mentioned above, but instead of going to a USB HDD or NAS, we're sending them to a cloud storage provider. Encryption, compression, de-duplication and versioning are features you can expect to find, and many of the apps I referenced previously are cloud-compatible. [BorgBackup](https://www.borgbackup.org/), [Restic](https://restic.net/), and [Duplicati](https://www.duplicati.com/) are all great options in this space.
|
||||
|
||||
**Advantages**
|
||||
|
||||
- **Secure** - Encryption allows you to use third-party hosting and storage services with fewer privacy and security concerns. They can't see your files, only the encrypted data.
|
||||
|
||||
- **Resilient** - Retention of multiple versions and built-in error checking lowers your chances of losing data significantly.
|
||||
|
||||
- **No hardware required** - No need to connect to local hard drive or network share, all you need is an internet connection and the backup will run in the background at a scheduled time.
|
||||
|
||||
- **Cheaper storage options than cloud sync** - Since device sync and web availability isn't a requirement for this type of backup, you're options are opened up to virtually any cloud storage vendor.
|
||||
|
||||
**Disadvantages**
|
||||
|
||||
- **Can still be expensive for high volumes** - While usually cheaper than cloud sync services, you'll still have to pay a subscription fee based on your usage.
|
||||
|
||||
- **Complexity** - Just like local backups, the applications take more work to set up than a simple sync service and the backups are stored in esoteric formats and folder structures.
|
||||
|
||||
**Best for**
|
||||
|
||||
- **Tier 1** - When your files are too large to practically store on a sync service. Also good for use in addition to a sync service.
|
||||
|
||||
## Local Backups - USB or NAS?
|
||||
|
||||
If you're starting from nothing, getting a USB hard drive will likely be your first step. If you don't have one lying around already, they can be purchased cheaply and are easy to plug in and use. However, if you can afford it, the ideal solution is either a pre-built NAS appliance (Synology, iXSystems, or QNAP) or a DIY NAS using either a traditional x86 PC or something like a Raspberry Pi or RockPro64. Either way, it's important to understand the advantages and limitations of both options.
|
||||
|
||||
### USB Hard Drives
|
||||
|
||||
**Advantages**
|
||||
|
||||
- **Cheap** - 4TB drives are less than $100 at most retailers.
|
||||
|
||||
- **Simple to set up** - Have you ever plugged in a USB cable before? That's it!
|
||||
|
||||
- **Portable** - Keep them on your desk or hide them in a drawer when you're done.
|
||||
|
||||
**Disadvantages**
|
||||
|
||||
- **Not good for laptops** - You probably don't want to carry your laptop around with a USB hard drive hanging out of it. With a mobile device, you'll have to remember to periodically plug it in and run the backup manually.
|
||||
|
||||
- **Current or resilient: pick one** - If you have a computer that can be tethered to a USB HDD 24/7, you can automate your backups and run them as often as you like. However, you then open yourself up to a single-point-of-failure situation where your O.S. could accidentally corrupt the data, or a disaster like an electrical surge or fire could take out both at once. To avoid this, you can detach the drive and store it in a secure location after the backup completes, but then you have to remember to plug it back in and your backups likely won't remain current as a result.
|
||||
|
||||
### NAS
|
||||
|
||||
**Advantages**
|
||||
|
||||
- **Shareable** - Since a NAS resides on your network, you can back up multiple laptops, desktops, and servers at once without having to plug in a cable.
|
||||
|
||||
- **Great for laptops** - Since you don't need to plug in a hard drive, your laptop can back itself up automatically at a scheduled time.
|
||||
|
||||
- **Separate from your devices** - Since a NAS is not directly connected to any one computer, the single-point-of-failure scenario is less likely.
|
||||
|
||||
**Disadvantages**
|
||||
|
||||
- **Pre-built devices can be expensive** - Even Synology's cheapest option with 4TB will be close to 4x the price of a USB hard drive with the same storage.
|
||||
- **Setup and maintenance** - Whether pre-built or custom, a NAS is a full computer running on your network that needs to be configured, updated, and maintained. To minimize this, choose a purpose-built device from Synology or QNAP.
|
||||
|
||||
## So what should you do?
|
||||
|
||||
Everybody's situation is different, but here are some general conclusions you can draw from this information:
|
||||
|
||||
1. **Tier 1** data should be backed up both locally and with a cloud sync or backup service.
|
||||
|
||||
2. **Tier 2** data should be backed up locally in at least one additional location.
|
||||
|
||||
3. Local backups are preferred over simple file syncs for their reliability and resiliency.
|
||||
|
||||
4. If you can't maintain a local backup, combine a cloud sync service with a cloud backup application.
|
||||
|
||||
5. **The most important thing is that you do *something***. Your data is too valuable and your computer's hard drive is too volatile to leave things up to chance.
|
||||
|
||||
## Bonus: What I Use
|
||||
|
||||
- Some **Tier 1** data is synced to a Nextcloud server hosted on DigitalOcean and that server is backed up to my local NAS using [BorgBackup](https://www.borgbackup.org/) and [Borgmatic](https://torsion.org/borgmatic/).
|
||||
|
||||
- All **Tier 1** data on my NAS is backed up nightly to [BorgBase](https://www.borgbase.com/) using BorgBackup and Borgmatic.
|
||||
|
||||
- **Tier 2** data on my NAS is backed up nightly to external hard drives using ZFS and [Sanoid/Syncpoid](https://github.com/jimsalterjrs/sanoid).
|
||||
|
||||
Have a great backup system of your own? As always, feel free to leave a comment or reach out to me directly with questions or feedback. Since BorgBackup is clearly a favorite of mine, I'll be sure to cover it in detail in a future post.
|
||||
|
||||
Thanks for reading and happy hacking!
|
||||
28
_posts/2022-01-07-kalendar.md
Normal file
28
_posts/2022-01-07-kalendar.md
Normal file
@@ -0,0 +1,28 @@
|
||||
---
|
||||
layout: single
|
||||
title: "I Was About to Write a To-Do App for the Linux Desktop... and then I found Kalendar."
|
||||
date: 2023-01-08 12:45:00
|
||||
excerpt: "2022 was a great year for my Python skills. I had some unique problems to solve in my day job that got me over the hump of learning the language, and finally I was able to write comfortably without googling syntax every five minutes..."
|
||||
categories: [Software Development]
|
||||
tags: linux python qt6 qt desktop kde kalendar
|
||||
comments: true
|
||||
---
|
||||
|
||||
{:class="img-responsive" .align-center}
|
||||
|
||||
2022 was a great year for my Python skills. I had some unique problems to solve in my day job that got me over the hump of learning the language, and finally I was able to write comfortably without Googling syntax every five minutes. Quickly my team's Github repo filled up with borderline-unnecessary one-off scripts to solve all sorts of niche problems in our environment. Due to the nature of being a system administrator at a SaaS-heavy company, most of these scripts deal with third-party APIs: moving data from "service a" to "service b", pulling information about "service c" and correlating it with "service d", etc. These types of scripts are fun to write because they have narrow scopes and easily achievable goals, and I find completing them to be immensely satisfying.
|
||||
|
||||
Filled with confidence in my Python skills, I set out to embark on my first GUI project: a desktop to-do application with CalDAV sync. This is an app I feel has been missing on Linux, something akin to Apple Reminders where I can use my own backend for sync. To get started, I built a local-only terminal client, bought a book to start learning PyQt, and I sat down today to write the first of a series of blog posts where I would document the project. I got to the part of the blog post where I confidently say that there are "currently no working Linux desktop apps with this functionality". Then I thought, *maybe I should Google this once more and confirm there really is nothing out there*. Well, shit.
|
||||
|
||||
## Enter Kalendar
|
||||
|
||||
The last time I researched this space, there were no functional standalone to-do apps that supported CalDAV sync. The closest I could find was Thunderbird, my beloved email client, which is far more complex than what I was looking for. [Kalendar](https://apps.kde.org/kalendar/) didn't even pop up on my radar. Even today when I searched, I almost didn't find it. I ended up seeing it on the [Nextcloud Tasks Github page](https://github.com/nextcloud/tasks#apps-which-sync-with-nextcloud-tasks-using-caldav) in a list of compatible apps with sync. Within minutes, I had it installed and synced with my tasks in Nextcloud, and **wow**, this thing is good.
|
||||
|
||||
Kalendar bills itself mainly as a new calendar app, but my task lists feel right at home here. The app opens instantly, and the task view is designed almost exactly as I envisioned for my own app; toggleable lists on the left and tasks on the right. Type on the bottom and hit enter to quickly create a new task and it syncs right up to Nextcloud. Right click on a task to easily set priority and due date, or add a subtask. I hate how good this is.
|
||||
|
||||
## What now?
|
||||
|
||||
I'm now a happy Kalendar user, and I've lost all motivation to write my own app, but I still want to learn GUI development! I've got remedial Python skills and my QT6 book ready to go! If this was ten years ago, there would probably be lots of voids to fill in the Linux app space, but as it stands today there are very few missing pieces. It feels like there's a great app for pretty much everything.
|
||||
|
||||
Does anyone have any desktop app ideas? Something missing from their day-to-day workflow? Are any projects you know of using PyQt that I could contribute to? Please let me know in the comments or send me a message. Trying to seize on some motivation here!
|
||||
|
||||
@@ -270,7 +270,7 @@ body:hover .visually-hidden button {
|
||||
|
||||
.fa-mastodon,
|
||||
.fa-mastodon-square {
|
||||
color: $mastodon-color;
|
||||
color: #000;
|
||||
}
|
||||
|
||||
.fa-pinterest,
|
||||
|
||||
BIN
assets/images/screenshots/kalendar01.png
Normal file
BIN
assets/images/screenshots/kalendar01.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 92 KiB |
BIN
assets/images/screenshots/nextcloud-photos-01.jpg
Normal file
BIN
assets/images/screenshots/nextcloud-photos-01.jpg
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 34 KiB |
BIN
assets/images/screenshots/nextcloud-photos-hero.png
Normal file
BIN
assets/images/screenshots/nextcloud-photos-hero.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 530 KiB |
Reference in New Issue
Block a user