Compare commits
14 commits
v25.5.D042
...
master
Author | SHA1 | Date | |
---|---|---|---|
4254b11819 | |||
403b16aab2 | |||
efac4343b1 | |||
fb63028ee2 | |||
844f2c1e2a | |||
a8bee6b8cd | |||
a2300c0eed | |||
fe9713d792 | |||
cf0223e99e | |||
018c74cad3 | |||
9f630196ed | |||
fafa5ee954 | |||
d736858945 | |||
6f6de59de0 |
|
@ -9,9 +9,10 @@ plugins:
|
|||
permalink: pretty
|
||||
baseurl: "/"
|
||||
url: "https://andrewconl.in"
|
||||
title: Andrew Conlin's blog
|
||||
|
||||
author: Andrew Conlin
|
||||
version: v25.5.D0425
|
||||
version: v25.9.U0517
|
||||
|
||||
defaults:
|
||||
# blog
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
<ul style="list-style-type:none;margin:0;padding:0;font-size:16px;">
|
||||
<ul style="list-style-type:none;margin:0;padding:0;">
|
||||
{% for post in site.posts %}
|
||||
{% assign category = post.category %}
|
||||
{% if category == page.title %}
|
||||
|
|
|
@ -1,4 +1,10 @@
|
|||
<span style="font-size: 24px;"><a href="/">andrewconl.in</a></span> <span style="color: #A89984;font-size:12px">is CSSing</span><br>
|
||||
<span style="font-size: 16px;word-spacing: 5px"><a href="/blog">blog</a> <a href="/til">til</a> <a href="/projects">projects</a> <a href="/meta">meta</a> <a href="/feed.xml">feed</a> <a href="/archive">[archive]</a></span>
|
||||
<span style="font-family: Geist Black;font-size: 24px;"><a href="/">andrewconl.in</a></span> <span style="color: #A89984;font-size:12px">is CSSing</span><br>
|
||||
<span style="font-family: Geist Black;font-size: 16px;word-spacing: 5px">
|
||||
<a href="/blog">blog</a>
|
||||
<a href="/til">til</a>
|
||||
<a href="/projects">projects</a>
|
||||
<a href="/meta">meta</a>
|
||||
<span style="word-spacing: 1px"><a href="/feed.xml">feed <img id="feed" src="/assets/images/icons/rss.svg" style="display: inline;height: 12px;"/></a></span>
|
||||
<a href="/archive">[archive]</a></span>
|
||||
<br>
|
||||
<hr>
|
||||
|
|
50
_includes/openringTemplate.html
Normal file
|
@ -0,0 +1,50 @@
|
|||
<!-- License-Id: CC0-1.0 -->
|
||||
<section class="webring">
|
||||
<p>Articles from blogs I follow around the net</p>
|
||||
<section class="articles">
|
||||
{{range .Articles}}
|
||||
<div class="article">
|
||||
<h4 class="title" dir="auto">
|
||||
<a href="{{.Link}}" target="_blank" rel="noopener">{{.Title}}</a>
|
||||
</h4>
|
||||
<p class="summary" dir="auto">{{.Summary}}</p>
|
||||
<small class="source">
|
||||
via <a href="{{.SourceLink}}">{{.SourceTitle}}</a>
|
||||
</small>
|
||||
<small class="date">{{.Date | datef "January 2, 2006"}}</small>
|
||||
</div>
|
||||
{{end}}
|
||||
</section>
|
||||
<p class="attribution">
|
||||
Generated by
|
||||
<a href="https://git.sr.ht/~sircmpwn/openring">openring</a>
|
||||
</p>
|
||||
</section>
|
||||
<style>
|
||||
.webring .articles {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
margin: -0.5rem;
|
||||
}
|
||||
.webring .title {
|
||||
margin: 0;
|
||||
}
|
||||
.webring .article {
|
||||
flex: 1 1 0;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
margin: 0.5rem;
|
||||
padding: 0.5rem;
|
||||
background: #32302F;
|
||||
min-width: 10rem;
|
||||
}
|
||||
.webring .summary {
|
||||
font-size: 0.8rem;
|
||||
flex: 1 1 0;
|
||||
}
|
||||
.webring .attribution {
|
||||
text-align: right;
|
||||
font-size: 0.8rem;
|
||||
color: #555;
|
||||
}
|
||||
</style>
|
|
@ -1,4 +1,6 @@
|
|||
<hr><br>
|
||||
<div style="text-align: center;">
|
||||
Issues or comments? <a href="mailto:andrew@andrewconl.in">Email me!</a>
|
||||
{% include openring.html %}
|
||||
<a href='https://ko-fi.com/H2H11DFIIR' target='_blank'><img height='36' style='border:0px;height:36px;' src='https://storage.ko-fi.com/cdn/kofi1.png?v=6' border='0' alt='Buy Me a Coffee at ko-fi.com' /></a><br>
|
||||
</div>
|
||||
|
|
|
@ -1,9 +1,9 @@
|
|||
---
|
||||
layout: default
|
||||
---
|
||||
<span style="font-size: 16px;"><a href="/">~</a> / <a href="/{{page.category}}">{{page.category}}</a> / <a href="">{{page.title}}</a><br></span>
|
||||
<span style="font-family: Geist Mono;font-size:16px;">
|
||||
{{ page.date | date: "%Y-%m-%d" }}<br>
|
||||
<span style="font-size: 16px;"><a href="/">~</a> / <a href="/{{page.category}}">{{page.category}}</a> / <a href="">{{page.title}}</a></span>
|
||||
<span style="font-family: Geist;font-size:14px;color: #A89984; float: right;">
|
||||
{{ page.date | date: "%Y-%m-%d" }} |
|
||||
{{ content | reading_time | pluralize: "minute" }}
|
||||
</span>
|
||||
<hr>
|
||||
|
|
|
@ -35,7 +35,7 @@ But where is the fun in that?! Something about this project wouldn't let me just
|
|||
|
||||
I started out by trying to just send commands to the screen. I knew the default address of the device from the datasheet (0x3C), and started firing commands over I2C to try and provoke any sort of reaction. The MicroZig driver allowed me to this super easily. Just setup the I2C device, and then send data using the `write_blocking` function. I put the sending code inside a little function to make things easier to parse:
|
||||
|
||||
```
|
||||
```zig
|
||||
const i2c0 = i2c.num(0);
|
||||
_ = i2c0.apply(.{
|
||||
.clock_config = rp2040.clock_config,
|
||||
|
@ -44,7 +44,7 @@ _ = i2c0.apply(.{
|
|||
.baud_rate = 400000,
|
||||
});
|
||||
```
|
||||
```
|
||||
```zig
|
||||
pub fn send(bytes: []const u8) !void {
|
||||
const a: i2c.Address = @enumFromInt(0x3C);
|
||||
_ = i2c0.write_blocking(a, bytes) catch {
|
||||
|
@ -57,7 +57,7 @@ The SSD1306, stood firm, resolutely denying me even a single pixel. There is no
|
|||
|
||||
It was at this point that I became really impressed with Zig's compilation, and in particular the caching. As part of this process, I was messing around a lot with my code, and then building and loading onto the Pico with the following command:
|
||||
|
||||
```
|
||||
```bash
|
||||
zig build; picotool load -x zig-out/firmware/pico_i2c.uf2
|
||||
```
|
||||
|
||||
|
@ -83,7 +83,7 @@ Surely I was almost there? Well, almost yes, but not quite. Matiasus's commands
|
|||
|
||||
The thing that made the breakthrough for me was [this holy grail of a blog post](https://nnarain.github.io/2020/12/01/SSD1306-OLED-Display-Driver-using-I2C.html). Just exactly what I needed at exactly the right time. It calmly and thoroughly explains the process of communicating with the display, as well as the initialisation. I was mostly right in what I interpreted from the datasheet, but it is always nice to have things confirmed by someone who clearly understands this better than you. This led me to the following initialisation commands:
|
||||
|
||||
```
|
||||
```zig
|
||||
const INIT = [_]u8{
|
||||
CONTROL_COMMAND, 0xAE,
|
||||
CONTROL_COMMAND, 0xA8, 0x1F,
|
||||
|
|
262
_posts/blog/2025-05-17-pizza-for-privacy.md
Normal file
|
@ -0,0 +1,262 @@
|
|||
---
|
||||
title: Pizza for privacy
|
||||
category: blog
|
||||
layout: post
|
||||
---
|
||||
|
||||
We recently received a suspicious letter though our door from something called 'The Origin Panel'. It described the details of an exclusive new research project, of which our household had been selected as special members! Wow, how exciting!
|
||||
|
||||
The letter immediately set off alarm bells for me and my partner. The project is being run by the ISBA (Incorporated Society of British Advertisers), and its stated aim is "to make advertising more relevant to you". This indicates that they want to collect data to target ads, and indeed this is the basis of the project, to allow us to "anonymously share \[our\] media habits". The letter is also filled with language designed to make the project sound legitimate and incentivize signups. "exciting new research project", "scientific sample", "invitation only". There is also a stated £100 available if you complete signup and installation (!) in four weeks.
|
||||
|
||||
This sounds terrible and awful and various other synonyms. Obviously we weren't going to sign up, but it begged to be looked into more. This post is the results of my investigation.
|
||||
|
||||
# # Who is behind the curtain?
|
||||
|
||||
The Origin Panel, henceforth referred to as Big Brother, provided a helpful link for us to get started: [www.theoriginpanel.uk](www.theoriginpanel.uk). The first question I had was "who is behind this?". Navigating to the About Us section of their website, we can find out that this operation is being run by a company called [Kantar](https://www.kantar.com/). They are a branding and advertising consultancy of the usual ilk, running this on behalf of the ISBA, as mentioned in their letter. This doesn't tell us much about who is actually behind it all, but I think you can probably already guess at the culprits. They provide this helpful description of their stated goals:
|
||||
|
||||
> \[Big Brother\] is ISBA’s advertiser backed programme, designed to create a blueprint for cross media measurement. It is part of a global initiative to capture the value of advertising in a constantly changing consumer environment.
|
||||
>
|
||||
> \[Big Brother\] is designed to address the needs of advertisers, who need to understand and plan campaigns across digital and broadcast platforms. They point out the lack of either a standardised approach to video and display measurement or a common measurement approach across media, particularly across digital platforms and between digital platforms and broadcaster TV.
|
||||
>
|
||||
> ISBA has been working with the WFA (World Federation of Advertisers) to convene advertisers, online platforms, and broadcasters to discuss a common global approach.
|
||||
|
||||
Sorting through the corporate waffle, this seems to part of a scheme to standardise tracking across both internet and traditional (broadcast) mediums to create a unified approach. Why anyone would want to help in this endeavour is beyond me.
|
||||
|
||||
After more poking around the website, I found what I was looking for. [This page](https://www.theoriginpanel.uk/OnlinePublishers) reveals the entities who get the collected data. Get your last guesses in now! And ... drumroll please ... it is ... Meta/Google/Amazon/TikTok. Keyser Soze and all that.
|
||||
|
||||
This page also contains "\[the\] approved list of websites, platforms or applications that our meters collect “Internet Data” from". So let's get into that.
|
||||
|
||||
# # What are you signing up for?
|
||||
|
||||
There have been various mentions so far of "installations" and "meters". So what would I actually have to do to get that sweet £100 bonus?
|
||||
|
||||
Watching through [the User Guides](https://www.theoriginpanel.uk/UserGuidePublic), there are two different types of meters that will be installed in your home when you sign up, one for each TV in your home, and one that plugs directly into the back of your router (!) that looks suspiciously like a Raspberry Pi in a case.
|
||||
|
||||
## ## The TV meter
|
||||
|
||||
The TV meters are a small touchscreen display that goes below the TV (and corresponding remote control).
|
||||
|
||||
<figure>
|
||||
<img src="/assets/images/origin-panel/whoispresent.png"/>
|
||||
<figcaption>Not disturbing at all!</figcaption>
|
||||
</figure>
|
||||
|
||||
Every time you watch TV, you have to indicate your presence. They also emphasise that you have to do it even if you just walk into a room where the TV is on.
|
||||
|
||||
<figure>
|
||||
<img src="/assets/images/origin-panel/helloSARAH.png"/>
|
||||
<figcaption>Normal human greeting</figcaption>
|
||||
</figure>
|
||||
|
||||
But don't worry, everyone gets a little avatar on the screen. You can even set up extra ones for guests! But only if they are strictly male or female. I guess non-binary people can't participate. Lucky for some!
|
||||
|
||||
<figure>
|
||||
<img src="/assets/images/origin-panel/removeallfemaleguests.png"/>
|
||||
<figcaption>A handy button for when you banish all women from your house</figcaption>
|
||||
</figure>
|
||||
|
||||
The device is constantly recording sound to identify which channel is being watched. I guess this works by detecting certain frequencies, but when Google and Amazon are involved, who knows.
|
||||
|
||||
## ## The router meter
|
||||
|
||||
This is definitely not a Raspberry Pi that you plug into the router.
|
||||
|
||||
<figure>
|
||||
<img src="/assets/images/origin-panel/rpi.png"/>
|
||||
<figcaption>Definitely not</figcaption>
|
||||
</figure>
|
||||
|
||||
It monitors your internet usage of a bunch of different sites, including but not limited to:
|
||||
|
||||
- Amazon Music
|
||||
- Amazon Prime
|
||||
- AppleTVPlus
|
||||
- Audible
|
||||
- BBC
|
||||
- BBC Sounds
|
||||
- DAZN
|
||||
- Discovery
|
||||
- Disney+
|
||||
- Facebook/Instagram
|
||||
- Google
|
||||
- Hayu
|
||||
- Lionsgate+
|
||||
- Netflix
|
||||
- NowTV
|
||||
- Paramount+
|
||||
- SkyGo
|
||||
- SkyMedia
|
||||
- SkyNews
|
||||
- Sound Cloud
|
||||
- Spotify
|
||||
- STV
|
||||
- TikTok
|
||||
- Twitch
|
||||
- UKTV
|
||||
- Viaplay
|
||||
- YouTube Music
|
||||
- ...
|
||||
- Full list here
|
||||
|
||||
They really try to emphasise that it will only monitor traffic from the sites they are interested in, but it must be processing all of your outgoing traffic to achieve this. Also, does it really matter if they are tracking everything that you Google search anyway?
|
||||
|
||||
There is a strange, almost urgent note in the [online meter PDF](https://www.theoriginpanel.uk/uploads/documents/UserGuides/Online%20meter%20guide%20v5.pdf):
|
||||
|
||||
> It’s essential that we preserve your privacy and anonymity so please don’t share your participation on the [Big Brother] with anyone you don’t know. You should also avoid mentioning your participation on the panel with anyone on social media, in or outside your circle of family and close friends
|
||||
|
||||
Surely, _surely_, if my data was being properly encrypted and anonymised, there would be no need for me to keep my participation a secret? There would be no way for the data to be connected back to me. Right guys? Right??
|
||||
|
||||
They also show their full router name and WiFi password in the video, while they talk about all the precautions they have taken with your data.
|
||||
|
||||
## ## Mobile app and software
|
||||
|
||||
There is also an app to download, which seems like it will pop-up every time you open your phone to ask who is using it. Looks like there is also some intrusive software to download directly onto you PC/laptop too, just so they don't miss anything!
|
||||
|
||||
Here is some information from their [Privacy Policy](https://www.theoriginpanel.uk/uploads/documents/OriginPrivacyPolicy.pdf)[^1] on the information that they collect:
|
||||
|
||||
> Kantar will collect the following types of information from the approved list of websites, platforms or applications you visit:
|
||||
>
|
||||
> - Information about the website, platform or applications you use such as:
|
||||
> - How long you visit the for;
|
||||
> - How often you visit;
|
||||
> - How you navigate through the website, platform or application;
|
||||
> - The advertisements you see.
|
||||
> - Information about the device you use such as:
|
||||
> - The device model and name;
|
||||
> - Operating system;
|
||||
> - MAC address;
|
||||
> - IP address;
|
||||
> - Other unique online identifiers such as Ad ID (Advertising Identifier).
|
||||
|
||||
Even more worryingly, the privacy policy indicates that your "pseudonymised" information will be directly shared with the companies involved:
|
||||
|
||||
> For some websites and apps, it is not possible to identify the
|
||||
> advertisements that you have seen through the Focal Meter and so we rely
|
||||
> on data from the online publishers themselves
|
||||
>
|
||||
> ...
|
||||
>
|
||||
> Kantar will share encrypted unique identifiers with the online publishers
|
||||
> (such as your email address or social media handle) or your device (such
|
||||
> as a mobile advertising ID or other unique device identifier associated
|
||||
> with the device you use) in a matching process. The online publisher will
|
||||
> use this identifier to provide us data that includes your online activity and
|
||||
> advertisements that have been shown to you on your device(s) (including
|
||||
> time stamps of when such content was shown to you) and share this
|
||||
> information with Kantar. In some instances we may also receive back
|
||||
> demographic information such as age bracket, sex and approximate
|
||||
> location (such as region or city) which is used for verification purposes.
|
||||
|
||||
<figure>
|
||||
<img src="/assets/images/origin-panel/baby.png"/>
|
||||
<figcaption>Oh, and don't forget to notify us if you have a newborn baby!</figcaption>
|
||||
</figure>
|
||||
|
||||
Now, it is obviously a terrible idea to sign up for this. You make it so easy for these companies to build up an advertising profile on you, and to develop newer, more intrusive technologies to get to the rest of us. You might be thinking "doesn't my ISP have all this information any way?". And you are (partially) right, your ISP can see all the sites you visit and the requests you make. But this process is evidently much more intrusive and insidious, with multiple devices and pieces of software collecting all the data they can. If they could get all this from your ISP, why would they need to install these devices?
|
||||
|
||||
You would be giving up all of your online privacy, for nothing. Well, not nothing, but we'll get into that next.
|
||||
|
||||
# # What do you get in return?
|
||||
|
||||
So, what is the incentive here? Apart from the £100 signup bonus, what do they give you in return for your privacy?
|
||||
|
||||
There is a page on their site that details the ["Reward Scheme"](https://www.theoriginpanel.uk/RewardSchemePublic) (uh oh).
|
||||
|
||||
Basically, in return for hoovering up all of your data you will collect points, which can then be redeemed at a specific list of shops. I couldn't find information on exactly where the points can be redeemed, nor any information about how many points you get each month. The [Terms & Conditions](https://www.theoriginpanel.uk/uploads/documents/Origin-TCs_v2-Legal-Entity-Update.pdf) say that 1000 points = £1, so it will likely take a while to get anything meaningful. One example they give in their promotional video is a pizza.
|
||||
|
||||
<figure>
|
||||
<img src="/assets/images/origin-panel/pizza.png"/>
|
||||
<figcaption>Tastes like freedom</figcaption>
|
||||
</figure>
|
||||
|
||||
They also say that there are monthly and quarterly prize draws, of up to £1000.
|
||||
|
||||
<figure>
|
||||
<img src="/assets/images/origin-panel/spend.png"/>
|
||||
<figcaption>"Spend" your points</figcaption>
|
||||
</figure>
|
||||
|
||||
So what do you get in return? Not a whole lot. Just some lousy vouchers that can only be spent at specific retailers under strict conditions, and entry into a lottery.
|
||||
|
||||
Don't worry though, you can be a good citizen and sacrifice your precious points to a "Kantar-approved charity"!
|
||||
|
||||
<figure>
|
||||
<img src="/assets/images/origin-panel/charity.png"/>
|
||||
<figcaption>Not sure what the local food bank is going to do with Kantar points</figcaption>
|
||||
</figure>
|
||||
|
||||
# # Does anyone actually sign up?
|
||||
|
||||
So surely nobody actually signs up for this? You would think, but humans never cease to amaze.
|
||||
|
||||
Looking at the [Big Brother's TrustPilot page](https://uk.trustpilot.com/review/theoriginpanel.uk), we can see a promising 2.2 average.
|
||||
|
||||
The reviews can be sorted into three categories:
|
||||
|
||||
1. People like me, complaining after having received the letter and done a little bit of research. These account for most of the 1 stars.
|
||||
2. Fake 5 star reviews. There is a lot of similar language being used throughout the 5 star reviews here. I have not done a proper analysis, but it definitely smells when all the 5 star reviews sound so similar. Looking forward to earning some rewards now!
|
||||
3. Real experiences. There does seem to be people who actually signed up, with both "good" and bad experiences.
|
||||
|
||||
<img src="/assets/images/origin-panel/andy.png"/>
|
||||
|
||||
<figure>
|
||||
<img src="/assets/images/origin-panel/customer.png"/>
|
||||
<figcaption>I am so glad "customer" likes their Pizza Hut salad</figcaption>
|
||||
</figure>
|
||||
|
||||
<img src="/assets/images/origin-panel/lisa.png"/>
|
||||
|
||||
<figure>
|
||||
<img src="/assets/images/origin-panel/pizzaforprivacy.png"/>
|
||||
<figcaption>Hey, that's the name of this post!</figcaption>
|
||||
</figure>
|
||||
|
||||
There are many reviews of people complaining about terrible customer service, and not being able to access their rewards or remove the software. For those who do seem to be enjoying it are content with \~£10 a month in vouchers. More than I expected, but still about 25 orders of magnitude away from the price of your privacy.
|
||||
|
||||
Either that, or pure financial exploitation:
|
||||
|
||||
<figure>
|
||||
<img src="/assets/images/origin-panel/struggle.png"/>
|
||||
<figcaption>Struggling financially</figcaption>
|
||||
</figure>
|
||||
|
||||
# # Bloody hell
|
||||
|
||||
The last thing I did was take a look at their [FAQs page](https://www.theoriginpanel.uk/FAQPublic), and things somehow got even worse.
|
||||
|
||||
Q: **What if we go on holiday?**
|
||||
> It is highly recommended that you inform our support team in advance if you are planning to go away. You can do this by calling or emailing us with your holiday dates. In order to check that the meters we send to panellists are functioning properly, we monitor TV viewing and Internet usage levels on a daily basis. If we are given notice that you will be away from the home, we will take your absence into account when monitoring usage.
|
||||
|
||||
A: **Please tell us every time your house is going to be empty for a while.**
|
||||
|
||||
Q: **Do you keep my children's information?**
|
||||
> In compliance with the Terms and Conditions of your panel membership, we do not release any TV or Web usage data connected to household members who are under the age of 16 for any analysis. No internet data is collected from such members, and the TV data we collect from those under the age of 16 is only used for quality control purposes within Kantar.
|
||||
|
||||
A: **Yes, yes we do.**
|
||||
|
||||
Q: **How long does the program last?**
|
||||
> The [Big Brother] program is an on-going project with no specific end date.
|
||||
|
||||
A: **FOREVER.**
|
||||
|
||||
Q: **Do you sell my data to advertisers?**
|
||||
> No, we do not pass on any details to advertisers or marketers. We may use third party service providers to assist in our administration of [Big Brother].
|
||||
|
||||
A: **No, we give it to them for free.**
|
||||
|
||||
Q: **Are you reading my children's messages?**
|
||||
> Our software is designed to only register when it detects audio and to communicate that back to our servers along with the source of that sound. We absolutely cannot read instant messages, emails or any other personal communications.
|
||||
|
||||
A: **No! We are just listening to their conversations!**
|
||||
|
||||
# # Conclusion
|
||||
It is frankly staggering that this exists. It baffles me that anyone would come up with such a scheme, let alone actually implement it! Advertising is a leech on our society, and the erosion of personal privacies and rights is something that we need to fight at every turn. Schemes like this should heavily regulated, if not outright illegal.
|
||||
|
||||
I cannot really blame the people getting £10 a month in vouchers, they are not the problem here. Inflation is high and money is hard to come by. The problem is the whole system, trying to squeeze out as much money as possible by monitoring everything we ever do or say, so they can sell it back to us.
|
||||
|
||||
(If there is anyone out there who has received one of these letters and is smarter (and braver) than me, I would love to see a proper teardown of these devices and a deep-dive into what is actually being tracked. Please, please, please write a big blog post about it.)
|
||||
|
||||
In conclusion, DO NOT SIGN UP FOR THIS. It is a massive invasion of your personal privacy, for little to nothing in return. If the product is free, YOU are the product. There is no such thing as free pizza.
|
||||
|
||||
<hr>
|
||||
[^1]: Surprised they have one!
|
|
@ -1,7 +1,7 @@
|
|||
---
|
||||
title: Fixing php errors in a Nextcloud docker-compose configuration
|
||||
categories:
|
||||
- til
|
||||
category: til
|
||||
layout: post
|
||||
tags:
|
||||
- php
|
||||
- nextcloud
|
||||
|
@ -15,7 +15,7 @@ I was trying to rescan the files in my Nextcloud server (running on Raspberry Pi
|
|||
|
||||
I was trying using the following syntax to call `occ` and scan the files:
|
||||
|
||||
```
|
||||
```bash
|
||||
sudo -u www-data php /path/to/nextcloud/occ files:scan --all
|
||||
```
|
||||
|
||||
|
@ -32,7 +32,7 @@ It took me a decent amount of time to diagnose the exact issue, but eventually I
|
|||
Running `php -m` will print out the list of currently installed PHP modules. I noticed I was missing quite a few of the required modules, but the one that was causing my issue was the missing `pdo_mysql` module.
|
||||
This can be installed by running:
|
||||
|
||||
```
|
||||
```bash
|
||||
sudo apt-get install php7.4-mysql
|
||||
```
|
||||
**Note: This command will change based on your OS, PHP version and database type**
|
||||
|
@ -49,7 +49,7 @@ From first glance, this looks like something wrong in the DNS name resolution. T
|
|||
Eventually however, after a long and perilous journey over the high seas of Nextcloud forums and StackOverflow, I found [this example](https://techoverflow.net/2020/07/17/how-to-run-nextcloud-php-occ-in-a-docker-compose-configuration/) of running `php occ` in a docker-compose configuration.
|
||||
This led me to running this command:
|
||||
|
||||
```
|
||||
```bash
|
||||
docker-compose exec -u www-data nextcloud-app php occ files:scan --all
|
||||
```
|
||||
**Note: replace nextcloud-app with the name of your Nextcloud container. Also, this command must be run from the directory of your Nextcloud docker-compose.yml**
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
---
|
||||
title: Running a Python script periodically in a Docker container using cron
|
||||
category: til
|
||||
layout: post
|
||||
---
|
||||
|
||||
Recently, my partner gave a great idea for utilising my old Kindle: generate a "newspaper" each morning from a bunch of RSS feeds, and email it to the Kindle using "Send-to-Kindle" feature (a blog post about this project is in the works).
|
||||
|
@ -10,7 +11,7 @@ I loved this idea, and thought it would be no problem to get a Python script up
|
|||
## 1. Double check the user
|
||||
|
||||
A lot of problems with `cron` come down to user privileges. Each user has their own `crontab`, and then there is the system-wide *root* `crontab`. The first issue I ran into with creating a `cron` job inside a container was that Docker created the crontab as a non-root user. This issue presented itself to me when I tried to run the following command, to list the current cronjobs in the Docker container:
|
||||
```
|
||||
```bash
|
||||
docker-compose exec container-name crontab -l
|
||||
```
|
||||
This returned the following output:
|
||||
|
@ -18,24 +19,24 @@ This returned the following output:
|
|||
no crontab for root
|
||||
```
|
||||
Now, it is not necessarily a problem to have non-root `cron` jobs, but just make absolutely certain that you are creating the jobs with the user you expect. For me, I wanted to run as `root`, so I added to following line to my docker-compose.yml:
|
||||
```
|
||||
```yaml
|
||||
user: root
|
||||
```
|
||||
Now, the `root` user will be used when building your Docker image and the created `crontab` will be where you expect.
|
||||
|
||||
## 2. Missing dependencies
|
||||
When `cron` calls your Python script, you may run into issues with `ModuleNotFoundError` or `ImportError`, where Python cannot find your installed packages. This is because `cron` does not have access to your system environment variables, including the Python path. You can resolve most of these errors with imports by adding the `PYTHONPATH` environment variable to your `crontab`. This should be the path to your `site-packages` folder, something like this:
|
||||
```
|
||||
```bash
|
||||
PYTHONPATH=/usr/bin/local/python3
|
||||
```
|
||||
You may also need to add a shebang (`#!`) to your Python script to direct `cron` to the correct version. You can find the Python location with one of the following commands:
|
||||
```
|
||||
```bash
|
||||
which python
|
||||
which py
|
||||
which python3
|
||||
```
|
||||
*NOTE*: These commands must be performed in your Docker container when it is up and running. In `docker-compose` syntax this would be the following (with the name of your container instead of `container-name`):
|
||||
```
|
||||
```bash
|
||||
docker-compose exec container-name which python3
|
||||
```
|
||||
You can then add this to the top of your Python script, as follows:
|
||||
|
@ -44,11 +45,11 @@ You can then add this to the top of your Python script, as follows:
|
|||
```
|
||||
## 3. Still missing dependencies
|
||||
Some modules will still run into errors even when the PYTHONPATH variable has been set. In particular, I ran into problems with `reportlab` and `Pillow/PIL`:
|
||||
```
|
||||
```python
|
||||
ImportError: cannot import name '_imaging' from 'PIL'
|
||||
```
|
||||
This was solved by adding the system PATH to the `crontab` as well. The system path is included in the default `crontab` that is created when you first run `crontab -e`:
|
||||
```
|
||||
```bash
|
||||
PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
|
||||
```
|
||||
Therefore, it is a good idea to include it if you are making a new `crontab` to make sure `cron` can find everything it needs to.
|
||||
|
@ -72,7 +73,7 @@ I was able to resolve these by adding `python3-dev`, `wheel` and `Cmake` to my `
|
|||
I hope this helped you resolve some errors! I've included my Dockerfile, docker-compose.yml and crontab below if you want to set up a similar project or adjust your own files. The full repo is also available [here](https://github.com/andrwcnln/watchman).
|
||||
|
||||
Dockerfile:
|
||||
```
|
||||
```docker
|
||||
FROM python:3
|
||||
|
||||
COPY . .
|
||||
|
@ -90,7 +91,7 @@ RUN crontab crontab
|
|||
CMD cron -f
|
||||
```
|
||||
docker-compose.yml:
|
||||
```
|
||||
```yaml
|
||||
version: "2.4"
|
||||
|
||||
services:
|
||||
|
@ -105,9 +106,9 @@ services:
|
|||
dockerfile: Dockerfile
|
||||
```
|
||||
crontab:
|
||||
```
|
||||
```cron
|
||||
PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
|
||||
PYTHONPATH=/usr/bin/local/python3
|
||||
15 7 * * * python3 /main.py >> /var/log/cron.log 2>&1
|
||||
|
||||
```
|
||||
```
|
||||
|
|
|
@ -25,11 +25,11 @@ Please visit https://rvm.io/integration/gnome-terminal/ for an example.
|
|||
So, we need to be in a login shell. Unfortunately, Alacritty does not have a settings GUI [like gnome-terminal](https://rvm.io/integration/gnome-terminal) and similar, and after thorough investigation I couldn't find a way to set this up through Alacritty. We need a different solution.
|
||||
|
||||
Luckily, this is possible through the shell itself. You can open a login shell by running the following command (press Ctrl+D to return to the interactive shell):
|
||||
```
|
||||
```bash
|
||||
bash --login
|
||||
```
|
||||
This also works with `zsh`, or Z-shell:
|
||||
```
|
||||
```bash
|
||||
zsh --login
|
||||
```
|
||||
Unfortunately for all you fishers out there, I couldn't find a way to to this with `fish`. If you know how, [send me an email!](mailto:andrew@andrewconl.in)
|
||||
|
|
|
@ -1,3 +1,5 @@
|
|||
@import "gruvbox.css";
|
||||
|
||||
@font-face {
|
||||
font-family: 'Geist';
|
||||
src: url('/assets/fonts/Geist-Regular.otf') format('opentype');
|
||||
|
@ -5,6 +7,13 @@
|
|||
font-style: normal;
|
||||
}
|
||||
|
||||
@font-face {
|
||||
font-family: 'Geist Black';
|
||||
src: url('/assets/fonts/Geist-Black.otf') format('opentype');
|
||||
font-weight: normal;
|
||||
font-style: normal;
|
||||
}
|
||||
|
||||
@font-face {
|
||||
font-family: 'Geist Mono';
|
||||
src: url('/assets/fonts/GeistMonoNerdFont-Regular.otf') format('opentype');
|
||||
|
@ -22,7 +31,7 @@ code {
|
|||
|
||||
div.container {
|
||||
margin: 0 auto;
|
||||
zoom: 1.5;
|
||||
zoom: 1.4;
|
||||
}
|
||||
|
||||
div.content {
|
||||
|
@ -41,7 +50,7 @@ div.content {
|
|||
}
|
||||
div.container {
|
||||
margin: 0 auto;
|
||||
zoom: 1.4
|
||||
zoom: 1.3
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -67,7 +76,7 @@ div.content {
|
|||
}
|
||||
div.container {
|
||||
margin: 0 auto;
|
||||
zoom: 1.0
|
||||
zoom: 1.1
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -98,6 +107,10 @@ a:hover {
|
|||
text-decoration: none;
|
||||
border-bottom: 2px solid #FABD2F;
|
||||
border-radius: 1px;
|
||||
|
||||
img.feed {
|
||||
filter: brightness(0) saturate(100%);
|
||||
}
|
||||
}
|
||||
|
||||
img {
|
||||
|
@ -132,10 +145,42 @@ span.growshrink {
|
|||
}
|
||||
}
|
||||
|
||||
p {
|
||||
body {
|
||||
font-size: 14px
|
||||
}
|
||||
|
||||
h1 {
|
||||
font-size: 24px
|
||||
}
|
||||
|
||||
hr {
|
||||
color: #32302F;
|
||||
border-color: #32302F
|
||||
}
|
||||
|
||||
blockquote {
|
||||
/* background-color:#32302F; */
|
||||
color: #A89984;
|
||||
font-style: italic;
|
||||
margin: 20px 0 30px;
|
||||
padding-left: 20px;
|
||||
border-left: 3px solid #A89984;
|
||||
max-width:90%;
|
||||
max-height:100%;
|
||||
margin-left: auto;
|
||||
margin-right: auto;
|
||||
display: block;
|
||||
}
|
||||
|
||||
figcaption {
|
||||
color: #A89984;
|
||||
text-align: center;
|
||||
max-width:70%;
|
||||
max-height:100%;
|
||||
margin-left: auto;
|
||||
margin-right: auto;
|
||||
display: block;
|
||||
font-size: 12px;
|
||||
font-style: italic;
|
||||
padding-top: 10px
|
||||
}
|
||||
|
|
73
assets/css/gruvbox.css
Normal file
|
@ -0,0 +1,73 @@
|
|||
.highlight .hll { background-color: #ffffcc }
|
||||
.highlight { background: #282828; color: #ebdbb2; background-color: #282828 }
|
||||
.highlight .c { color: #928374; font-style: italic; background-color: #282828 } /* Comment */
|
||||
.highlight .err { color: #ebdbb2; background-color: #282828 } /* Error */
|
||||
.highlight .esc { color: #ebdbb2; background-color: #282828 } /* Escape */
|
||||
.highlight .g { color: #ebdbb2; background-color: #282828 } /* Generic */
|
||||
.highlight .k { color: #fe8019; background-color: #282828 } /* Keyword */
|
||||
.highlight .l { color: #ebdbb2; background-color: #282828 } /* Literal */
|
||||
.highlight .n { color: #ebdbb2; background-color: #282828 } /* Name */
|
||||
.highlight .o { color: #fe8019; background-color: #282828 } /* Operator */
|
||||
.highlight .x { color: #ebdbb2; background-color: #282828 } /* Other */
|
||||
.highlight .p { color: #ebdbb2; background-color: #282828 } /* Punctuation */
|
||||
.highlight .ch { color: #928374; font-style: italic; background-color: #282828 } /* Comment.Hashbang */
|
||||
.highlight .cm { color: #928374; font-style: italic; background-color: #282828 } /* Comment.Multiline */
|
||||
.highlight .cp { color: #8ec07c; background-color: #282828 } /* Comment.Preproc */
|
||||
.highlight .c1 { color: #928374; font-style: italic; background-color: #282828 } /* Comment.Single */
|
||||
.highlight .cs { color: #928374; font-style: italic; background-color: #282828 } /* Comment.Special */
|
||||
.highlight .gd { color: #282828; background-color: #fb4934 } /* Generic.Deleted */
|
||||
.highlight .ge { color: #83a598; text-decoration: underline; background-color: #282828 } /* Generic.Emph */
|
||||
.highlight .gr { color: #ebdbb2; font-weight: bold; background-color: #fb4934 } /* Generic.Error */
|
||||
.highlight .gh { color: #b8bb26; font-weight: bold; background-color: #282828 } /* Generic.Heading */
|
||||
.highlight .gi { color: #282828; background-color: #b8bb26 } /* Generic.Inserted */
|
||||
.highlight .go { color: #504945; background-color: #282828 } /* Generic.Output */
|
||||
.highlight .gp { color: #ebdbb2; background-color: #282828 } /* Generic.Prompt */
|
||||
.highlight .gs { color: #ebdbb2; background-color: #282828 } /* Generic.Strong */
|
||||
.highlight .gu { color: #b8bb26; font-weight: bold; background-color: #282828 } /* Generic.Subheading */
|
||||
.highlight .gt { color: #ebdbb2; font-weight: bold; background-color: #fb4934 } /* Generic.Traceback */
|
||||
.highlight .kc { color: #fe8019; background-color: #282828 } /* Keyword.Constant */
|
||||
.highlight .kd { color: #fe8019; background-color: #282828 } /* Keyword.Declaration */
|
||||
.highlight .kn { color: #fe8019; background-color: #282828 } /* Keyword.Namespace */
|
||||
.highlight .kp { color: #fe8019; background-color: #282828 } /* Keyword.Pseudo */
|
||||
.highlight .kr { color: #fe8019; background-color: #282828 } /* Keyword.Reserved */
|
||||
.highlight .kt { color: #fabd2f; background-color: #282828 } /* Keyword.Type */
|
||||
.highlight .ld { color: #ebdbb2; background-color: #282828 } /* Literal.Date */
|
||||
.highlight .m { color: #d3869b; background-color: #282828 } /* Literal.Number */
|
||||
.highlight .s { color: #b8bb26; background-color: #282828 } /* Literal.String */
|
||||
.highlight .na { color: #b8bb26; font-weight: bold; background-color: #282828 } /* Name.Attribute */
|
||||
.highlight .nb { color: #fabd2f; background-color: #282828 } /* Name.Builtin */
|
||||
.highlight .nc { color: #ebdbb2; background-color: #282828 } /* Name.Class */
|
||||
.highlight .no { color: #d3869b; background-color: #282828 } /* Name.Constant */
|
||||
.highlight .nd { color: #ebdbb2; background-color: #282828 } /* Name.Decorator */
|
||||
.highlight .ni { color: #fabd2f; background-color: #282828 } /* Name.Entity */
|
||||
.highlight .ne { color: #fb4934; background-color: #282828 } /* Name.Exception */
|
||||
.highlight .nf { color: #fabd2f; background-color: #282828 } /* Name.Function */
|
||||
.highlight .nl { color: #fb4934; background-color: #282828 } /* Name.Label */
|
||||
.highlight .nn { color: #ebdbb2; background-color: #282828 } /* Name.Namespace */
|
||||
.highlight .nx { color: #ebdbb2; background-color: #282828 } /* Name.Other */
|
||||
.highlight .py { color: #ebdbb2; background-color: #282828 } /* Name.Property */
|
||||
.highlight .nt { color: #fb4934; background-color: #282828 } /* Name.Tag */
|
||||
.highlight .nv { color: #ebdbb2; background-color: #282828 } /* Name.Variable */
|
||||
.highlight .ow { color: #fe8019; background-color: #282828 } /* Operator.Word */
|
||||
.highlight .w { color: #ebdbb2; background-color: #282828 } /* Text.Whitespace */
|
||||
.highlight .mb { color: #d3869b; background-color: #282828 } /* Literal.Number.Bin */
|
||||
.highlight .mf { color: #d3869b; background-color: #282828 } /* Literal.Number.Float */
|
||||
.highlight .mh { color: #d3869b; background-color: #282828 } /* Literal.Number.Hex */
|
||||
.highlight .mi { color: #d3869b; background-color: #282828 } /* Literal.Number.Integer */
|
||||
.highlight .mo { color: #d3869b; background-color: #282828 } /* Literal.Number.Oct */
|
||||
.highlight .sb { color: #b8bb26; background-color: #282828 } /* Literal.String.Backtick */
|
||||
.highlight .sc { color: #b8bb26; background-color: #282828 } /* Literal.String.Char */
|
||||
.highlight .sd { color: #b8bb26; background-color: #282828 } /* Literal.String.Doc */
|
||||
.highlight .s2 { color: #b8bb26; background-color: #282828 } /* Literal.String.Double */
|
||||
.highlight .se { color: #b8bb26; background-color: #282828 } /* Literal.String.Escape */
|
||||
.highlight .sh { color: #b8bb26; background-color: #282828 } /* Literal.String.Heredoc */
|
||||
.highlight .si { color: #b8bb26; background-color: #282828 } /* Literal.String.Interpol */
|
||||
.highlight .sx { color: #b8bb26; background-color: #282828 } /* Literal.String.Other */
|
||||
.highlight .sr { color: #b8bb26; background-color: #282828 } /* Literal.String.Regex */
|
||||
.highlight .s1 { color: #b8bb26; background-color: #282828 } /* Literal.String.Single */
|
||||
.highlight .ss { color: #83a598; background-color: #282828 } /* Literal.String.Symbol */
|
||||
.highlight .bp { color: #fabd2f; background-color: #282828 } /* Name.Builtin.Pseudo */
|
||||
.highlight .vc { color: #ebdbb2; background-color: #282828 } /* Name.Variable.Class */
|
||||
.highlight .vg { color: #ebdbb2; background-color: #282828 } /* Name.Variable.Global */
|
||||
.highlight .vi { color: #ebdbb2; background-color: #282828 } /* Name.Variable.Instance */
|
||||
.highlight .il { color: #d3869b; background-color: #282828 } /* Literal.Number.Integer.Long */
|
BIN
assets/fonts/Geist-Black.otf
Normal file
7
assets/images/icons/rss.svg
Normal file
|
@ -0,0 +1,7 @@
|
|||
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
|
||||
<!-- Uploaded to: SVG Repo, www.svgrepo.com, Transformed by: SVG Repo Mixer Tools -->
|
||||
<svg width="800px" height="800px" viewBox="0 0 10 10" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" fill="#E7D7AD" stroke="#E7D7AD">
|
||||
<g id="SVGRepo_bgCarrier" stroke-width="0"/>
|
||||
<g id="SVGRepo_tracerCarrier" stroke-linecap="round" stroke-linejoin="round"/>
|
||||
<g id="SVGRepo_iconCarrier"> <title>rss [#1028]</title> <desc>Created with Sketch.</desc> <defs> </defs> <g id="Page-1" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd"> <g id="Dribbble-Light-Preview" transform="translate(-65.000000, -3644.000000)" fill="#E7D7AD"> <g id="icons" transform="translate(56.000000, 160.000000)"> <path d="M9.01405871,3491.9522 L9.01405871,3492.95455 C9.01405871,3493.50785 9.46393743,3493.9569 10.0182523,3493.9569 L11.0224458,3493.9569 C11.0224458,3492.8493 10.1236926,3491.9522 9.01405871,3491.9522 M9,3487.94279 L9,3489.94749 C11.215251,3489.94749 13.0167743,3491.9953 13.0167743,3494 L15.0251614,3494 C15.0251614,3490.99295 12.3278975,3487.94279 9,3487.94279 M18.9937344,3492.85231 C19.0600112,3493.45071 18.592057,3494 17.9895408,3494 L17.0476073,3494 C17.0476073,3489.99059 13.0167743,3485.93809 9,3485.93809 L9,3484.99788 C9,3484.39647 9.53623937,3483.9394 10.1347387,3484.00656 C14.7801382,3484.52477 18.4745663,3488.21643 18.9937344,3492.85231" id="rss-[#1028]"> </path> </g> </g> </g> </g>
|
||||
</svg>
|
After Width: | Height: | Size: 1.5 KiB |
BIN
assets/images/origin-panel/andy.png
Normal file
After Width: | Height: | Size: 120 KiB |
BIN
assets/images/origin-panel/baby.png
Normal file
After Width: | Height: | Size: 28 KiB |
BIN
assets/images/origin-panel/charity.png
Normal file
After Width: | Height: | Size: 66 KiB |
BIN
assets/images/origin-panel/customer.png
Normal file
After Width: | Height: | Size: 198 KiB |
BIN
assets/images/origin-panel/helloSARAH.png
Normal file
After Width: | Height: | Size: 360 KiB |
BIN
assets/images/origin-panel/lisa.png
Normal file
After Width: | Height: | Size: 200 KiB |
BIN
assets/images/origin-panel/pizza.png
Normal file
After Width: | Height: | Size: 682 KiB |
BIN
assets/images/origin-panel/pizzaforprivacy.png
Normal file
After Width: | Height: | Size: 208 KiB |
BIN
assets/images/origin-panel/removeallfemaleguests.png
Normal file
After Width: | Height: | Size: 386 KiB |
BIN
assets/images/origin-panel/rpi.png
Normal file
After Width: | Height: | Size: 335 KiB |
BIN
assets/images/origin-panel/spend.png
Normal file
After Width: | Height: | Size: 83 KiB |
BIN
assets/images/origin-panel/struggle.png
Normal file
After Width: | Height: | Size: 284 KiB |
BIN
assets/images/origin-panel/whoispresent.png
Normal file
After Width: | Height: | Size: 315 KiB |
13
deploy.sh
Normal file
|
@ -0,0 +1,13 @@
|
|||
openring \
|
||||
-s https://andyconlin.com/feed/ \
|
||||
-s https://digitalflapjack.com/blog/index.xml \
|
||||
-s https://gpanders.com/index.xml \
|
||||
-s https://luke.hsiao.dev/atom.xml \
|
||||
-s https://wickstrom.tech/feed.xml \
|
||||
-s https://paulcapewell.com/feed/ \
|
||||
-s https://www.splitbrain.org/feed/blog \
|
||||
-s https://lilysthings.org/blog/rss.xml \
|
||||
< _includes/openringTemplate.html \
|
||||
> _includes/openring.html
|
||||
bundle exec jekyll build
|
||||
rsync -r _site andrew@itchy:/home/andrew/site
|
BIN
favicon.ico
Normal file
After Width: | Height: | Size: 2.2 KiB |
|
@ -4,7 +4,7 @@ title: projects
|
|||
---
|
||||
|
||||
{% include pageTitle.html %}
|
||||
<ul style="list-style-type:none;margin:0;padding:0;font-size:16px;">
|
||||
<ul style="list-style-type:none;margin:0;padding:0;">
|
||||
<p><span style="font-family:Geist Mono"><a href="https://pypi.org/project/tictoc">tictoc</a> / </span>Fast, simple and accurate Python timing. Written in Rust.</p>
|
||||
<p><span style="font-family:Geist Mono"><a href="https://year-progress.cnln.dev">year-progress</a> / </span>A fun side project which gives the progress through the year, relative to other things.</p>
|
||||
</ul>
|
||||
|
|
12
serve.sh
Normal file
|
@ -0,0 +1,12 @@
|
|||
openring \
|
||||
-s https://andyconlin.com/feed/ \
|
||||
-s https://digitalflapjack.com/blog/index.xml \
|
||||
-s https://gpanders.com/index.xml \
|
||||
-s https://luke.hsiao.dev/atom.xml \
|
||||
-s https://wickstrom.tech/feed.xml \
|
||||
-s https://paulcapewell.com/feed/ \
|
||||
-s https://www.splitbrain.org/feed/blog \
|
||||
-s https://lilysthings.org/blog/rss.xml \
|
||||
< _includes/openringTemplate.html \
|
||||
> _includes/openring.html
|
||||
bundle exec jekyll serve
|