tag:blogger.com,1999:blog-43166970035230671612024-03-13T15:46:30.506-07:00Desra BlogDesrahttp://www.blogger.com/profile/10672334333562822105noreply@blogger.comBlogger95125tag:blogger.com,1999:blog-4316697003523067161.post-56598105685794139212021-02-26T18:12:00.005-08:002021-02-26T18:12:58.915-08:00decoding base64 signed urls in varnishFronting imgproxy with varnish, to honor old url base64 signed urls
<p>the javascript file</p>
<pre><code class="js">
vcl 4.0;
import blob;
import digest;
# Default backend definition. Set this to point to your content server.
backend default {
.host = "127.0.0.1";
.port = "8080";
}
sub vcl_init {
}
sub vcl_recv {
set req.http.base64part = regsub(req.url, "^/testpath/(.*)\.(.*)$", "\1");
set req.http.base64ashex = blob.transcode(encoding=HEX, decoding=BASE64URL, encoded=req.http.base64part);
set req.http.imghash-hex = regsub(req.http.base64asHex, "^(.{0,64})(.*)$", "\1");
set req.http.imgauth-hex = regsub(req.http.base64asHex, "^(.{0,64})(.{0,32})(.*)$", "\2");
set req.http.imgparms-hex = regsub(req.http.base64asHex, "^(.{0,96})(.*)$", "\2");
set req.http.imgparms = blob.transcode(encoding=IDENTITY, decoding=HEX, encoded=req.http.imgparms-hex);
set req.http.genimgauth = digest.hash_md5(req.http.imghash-hex + "-" + req.http.imgparms + "-" + "mymagicsecret");
if (req.http.genimgauth == req.http.imgauth-hex) {
set req.http.imgsig="good";
} else {
set req.http.imgsig="bad";
}
unset req.http.decodedUrl;
unset req.http.imghash;
unset req.http.imgauth;
set req.http.fileExt = regsub(req.url, "^/ddimgnew/(.*)\.(.*)$", "\2");
set req.http.origurl = req.url;
set req.http.bucketUrl = regsub(req.http.imgparms, "(.*)\|(.*)\|(.*)\|(.*)\|(.*)\|(.*)\|(.*)\|(.*)\|(.*)\|(.*)\|(.*)\|(.*)", "\1");
set req.http.imgFormat = "jpg";
if (req.http.fileExt == "webp") {
set req.http.imgFormat = "webp";
}
if (regsub(req.http.imgparms, ".*\|(.*)\|(.*)\|(.*)\|(.*)\|(.*)\|(.*)\|(.*)\|(.*)\|(.*)\|(.*)\|(.*)", "\3") != "") {
set req.http.imgMode = "fit";
set req.http.imgH = regsub(req.http.imgparms, ".*\|(\d+)x(\d+)\|.*", "\1");
set req.http.imgW = regsub(req.http.imgparms, ".*\|(\d+)x(\d+)\|.*", "\2");
}
if (regsub(req.http.imgparms, ".*\|(.*)\|(.*)\|(.*)\|(.*)\|(.*)\|(.*)\|(.*)\|(.*)\|(.*)\|(.*)\|(.*)", "\6") != "") {
set req.http.imgMode = "fill";
set req.http.imgH = regsub(req.http.imgparms, ".*\|(\d+)x(\d+)\|.*", "\1");
set req.http.imgW = regsub(req.http.imgparms, ".*\|(\d+)x(\d+)\|.*", "\2");
}
set req.http.imgproxyUrl = "mangled/" + req.http.imgMode + "/" + req.http.imgH + "/" + req.http.imgW + "/ce/0/plain/" + req.http.bucketUrl + "@" + req.http.imgFormat;
set req.url = "/mangled/" + req.http.imgMode + "/" + req.http.imgH + "/" + req.http.imgW + "/ce/0/plain/" + req.http.bucketUrl + "@" + req.http.imgFormat;
return (hash);
}
sub vcl_deliver {
set resp.http.imgsig = req.http.imgsig;
set resp.http.origurl = req.http.origurl;
set resp.http.backendurl = req.url;
}
sub vcl_hash {
hash_data(req.url);
if (req.http.host) {
hash_data(req.http.host);
} else {
hash_data(server.ip);
}
return (lookup);
}
sub vcl_backend_fetch {
return (fetch);
}
</code></pre>
Desrahttp://www.blogger.com/profile/10672334333562822105noreply@blogger.com0tag:blogger.com,1999:blog-4316697003523067161.post-6652339966922783882021-02-16T15:25:00.007-08:002021-02-19T18:12:53.009-08:00nginx decode base64 url for use with imgproxy<p> i've been testing imgproxy, to handle our image serving needs, and it looks good.</p><p>our existing servers are php based, and we sign and encode our urls for images. To test out imgproxy , I wanted to simply drop it in as a replacement for our servers by sending a % of traffic. </p><p>There are many ways to do this, varnish was one, with custom code, but nginx is our go-to web server, so I had to find a way to have nginx sit in front of imgproxy and rewrite the decoded url.</p><p>I settled on using njs, the cut down version of javascript that plugs into nginx as a loadable module. Then use proxy_pass to pass the uri to javascript that will return the imgproxy compatable url, and proxy to it.</p><p>a sample url would be</p><p>http://foo.bar/images/c2lnbmF0dXJlZm9vaHR0cDovL3MzLWV1LXdlc3QtMS5hbWF6b25hd3MuY29tL215YnVja2V0b2ZwaG90b3MvcGhvdG9fb2ZfYV9jYXQ1fHx8MTIwMHgxMjAwfHx8fHx8fHw==.jpeg</p><p>it has a sig, a bucket url, and parameters like image size.</p><p>Getting nginx setup</p>
<p>nginx.conf</p>
<pre><code class="bash">load_module modules/ngx_http_js_module.so;
</code></pre>
<div><div>in /etc/nginx/sites-enabled/default</div><div><br /></div><div>
<pre><code class="bash">js_include "imgproxyurl.js";
js_set $imgproxyurl imgproxyurl;
server {
location ~ /images/(.*) {
aio threads;
proxy_buffering off;
proxy_pass $imgproxyurl;
}
</code></pre>
<p><br /></p><p>the javascript file</p>
<pre><code class="js">
function imgproxyurl(r) {
var splitUrl = r.uri.split('\/');
var filePart = splitUrl[2];
var decodedUrl = Buffer.from(filePart, 'base64url'); // don't make a string, it can have binary data , base64url takes care of + /
// skip anything up to position 48, which is the bucket part of the url
var justParams = decodedUrl.slice(48).toString(); // string it after slicing the binary contents
var splitParams = justParams.split('|');
var bucketUrl = splitParams[0];
// take parameters from the url and use them to shape the imgproxy url
var imgMode = 'fit';
if (splitParams[3] != '') var imgSize = splitParams[3];
if (splitParams[6] != '') {
var imgSize = splitParams[6];
imgMode = 'fill';
}
var imgSizeParts = imgSize.split('x');
var imgH = imgSizeParts[0];
var imgW = imgSizeParts[1];
// make image format based on extension in url
var imgFormat = 'jpg';
if (r.uri.substring(r.uri.length -4, r.uri.length) === "webp") imgFormat = 'webp';
// imgproxy is running localhost, no need to encode or encrypt url, it's invisible
var newUrl = 'http://127.0.0.1:8080/donedeal/' + imgMode + '/' + imgH + '/' + imgW + '/ce/0/plain/' + bucketUrl + '@' + imgFormat;
//r.headersOut['debug-hint'] = [newUrl];
return(newUrl);
}
</code></pre>
<div><br /></div>Desrahttp://www.blogger.com/profile/10672334333562822105noreply@blogger.com0tag:blogger.com,1999:blog-4316697003523067161.post-57889039101732634152021-02-06T10:42:00.004-08:002021-02-06T10:43:29.614-08:00running a victoriametrics cluster<p>I recently had a need to work with metrics, and looking at the landscape of modern tools, went with victoriametrics.
After initially using the single binary version, I went on to setup the cluster version, using two nodes for everything (free nodes in oracles free tier!)
run these binaries on each node (where 10.0.2.41 and 10.0.2.40 are the addresses of the nodes)
</p>
<pre><code class="bash">
./vmstorage-prod -retentionPeriod 5y -storageDataPath /var/lib/victoriametrics
./vminsert-prod -storageNode=10.0.2.41:8400 -storageNode=10.0.2.40:8400 -replicationFactor=2
./vmselect-prod -storageNode=10.0.2.41:8401 -storageNode=10.0.2.40:8401 -replicationFactor=2 -dedup.minScrapeInterval=1ms
</code></pre>
<p>front vmselect and vminsert with nginx</p>
<pre><code class="bash">
server {
listen 443 ssl;
server_name metrics.foo.bar;
location /insert/ {
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_pass http://localhost:8480;
}
location /select/ {
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_pass http://localhost:8481;
}
</code></pre>
<p>
use certbot to get a letsencrypt cert, it will configure nginx for you (if you installed python3-certbot-nginx ) There is no auth of any kind, because i chose to front it with cloudflare, using the loadbalancer function to front the two nodes , and locked down nginx to cloudflare ips</p>
<pre><code class="bash">
server {
include /etc/nginx/cloudflare-allow.conf;
allow 127.0.0.1/32;
deny all;
</code></pre>
<p>in cloudflare I setup that a cert is required to access the fqdn , therefore making the whole system require cert auth to read or write metrics
I send metrics with telegraf , and this config</p>
<pre><code class="bash">
[[outputs.influxdb]]
urls = ["https://metrics.foo.bar:443/insert/0/influx"]
database = "whatever"
tls_cert = "/etc/telegraf/cloudflare.user.crt"
tls_key = "/etc/telegraf/cloudflare.user_nopass.key"
</code></pre>
<p>
and grafana works fine with those certs too
</p>
Desrahttp://www.blogger.com/profile/10672334333562822105noreply@blogger.com0tag:blogger.com,1999:blog-4316697003523067161.post-14842780020552011112021-02-06T09:03:00.003-08:002021-02-06T10:44:48.231-08:00using vmctl to copy dataI had a need to copy data from a standalone victoriametrics system to a cluster setup. for some reason the command line wasn't intuitive, so making a note here
<div><br /></div>
<pre><code class="bash">
./vmctl vm-native --vm-native-src-addr=https://source.to.copy.from:443
--vm-native-src-user user1 --vm-native-src-password password1
--vm-native-dst-addr=https://destination.to.copy.to:443/insert/0/prometheus/api/v1/write
--vm-native-filter-match='{db="db1"}'
</code></pre>Desrahttp://www.blogger.com/profile/10672334333562822105noreply@blogger.com0tag:blogger.com,1999:blog-4316697003523067161.post-25909000556058912862021-02-06T08:57:00.004-08:002021-02-06T08:57:34.424-08:00using vmagent to collect victoriametrics stats<p> vmagent is part of victoriametrics, and is a lightweight prometheus scraper.</p><p>create a basic prometheus.yml file that defines a host to scrape, in this example it's using SSL and basic auth</p><p><br /></p>
<pre><code class="yaml">
global:
scrape_interval: 15s
evaluation_interval: 15s
scrape_configs:
- job_name: vmetrics
static_configs:
- targets:
- host.to.scrape:443
scheme: https
basic_auth:
username: user1
password: password1
</code></pre>
<p>then run vmagent to use this and send to a victoriametrics node to store the metrics it scrapes</p><p><br /></p>
<pre><code class="bash">
./vmagent-prod -httpListenAddr 127.0.0.1:8240 -remoteWrite.basicAuth.username user2
-remoteWrite.basicAuth.password 'password2'
-remoteWrite.url=https://host.to.send.to:443/api/v1/write
-promscrape.config=prometheus.dsch.yml
</code></pre>
<p>if using the cluster version, the url in the command line might be</p><p><br /></p>
<pre><code class="bash">
-remoteWrite.url=https://host.to.send.to:443/insert/0/prometheus/api/v1/write
</code></pre>
Desrahttp://www.blogger.com/profile/10672334333562822105noreply@blogger.com0tag:blogger.com,1999:blog-4316697003523067161.post-16769887935089423512020-10-26T10:28:00.004-07:002021-02-06T08:46:34.995-08:00de-bouncing an S0 energy sensor on a piI hooked up a submeter to my fuseboard some time ago, and not too long ago I started to read it with a Pi Zero. <div>However every now and again I would get a crazy reading, and from logging I would see bouncing.
I would see interrupts where wiringpi would report the input as 0, and then again as 0, with no change to 1 inbetween. </div><div>I read up on debouncing and how the Pi is meant to do this, and also how some people have handled it in code by removing large deviations. </div><div> In my case, the solution has been to simply add logic in an encompassing if statement, to ignore interrupts where the pin is the same value as the last interrupt, and only count interrupts where the pin is a different like this
</div><div><br /></div><div><br /></div>
<pre><code class="cpp">
if (digitalRead(PIN) == last_interrupt_pin) {
printf("Bounce ! Last Pin = %d This Pin = %d\n",
digitalRead(PIN),
last_interrupt_pin);
}
</code></pre>Desrahttp://www.blogger.com/profile/10672334333562822105noreply@blogger.com0tag:blogger.com,1999:blog-4316697003523067161.post-22735080217257462392020-09-25T05:32:00.003-07:002020-09-25T13:56:35.264-07:00day night meter<p> I recently looked at moving from a basic electricity meter to a day/night meter, and got a little caught up in the maths, so thought I write it here.</p><p>Where I live, your electricity is made up of a standing monthly charge, and a usage charge. you by default get a meter which is an all day meter and not aware of day/night. though smart meters are coming (smart tarriffs some other time in the future).</p><p>For free you can change your meter to be a day night meter, where the day tariff is higher than the all day tariff, but the night tariff is a lot cheaper. The standing rate is different, but lets ignore that or now.</p><p>There is a magic point where your % of electrcity used during the day vs night, will be equal to the cost of the all day tariff, and expressing this lets you figure out if you will save money moving from all day to day/night. The maths looks like this</p><p><span style="font-family: courier;">(night rate - all day rate) / (night rate - day rate) = %day </span> (the percent of you 24hr usage that must be in 'day' time</p><p>In my case, standard all day rate is 0.1426 c per kwh , day rate = 0.154 and night rate = 0.0839</p><p>using that math above, 84% is the magic number. if I used < 84% of my daily electricity during the day, I will save money. My current usage is 70/30 so savings will be achieved :)</p><p><br /></p><p>Now, about standing rates ... for this example, the all day standing rate is 0.52c a day, and day/night is .70c a day, this can be expressed that to save this 18c difference a day, moving 3kwh from day to night would give 0.18/(0.1426-0.0839) = 3.06 or 3kwh.</p><p><br /></p><p>The final answer is that I must be 84% or less usage is day, and an additional 3kwh must move to night to save money</p>
<script async="" src="//jsfiddle.net/sloppymoppy/u5qzwor9/19/embed/result/dark/"></script>Desrahttp://www.blogger.com/profile/10672334333562822105noreply@blogger.com0tag:blogger.com,1999:blog-4316697003523067161.post-86572065576989300822020-03-24T15:38:00.001-07:002020-03-24T17:59:23.433-07:00installing windows 10 on a mac mini 2,1<div dir="ltr" style="text-align: left;" trbidi="on">
Mac mini 2,1 devices are tricky, they are 64bit, but have a 32bit EFI. booting a usb to install windows isn't going to work.<br />
<br />
my internal cdrom drive is faulty, so can't use that<br />
an external cdrom won't install either.<br />
<br />
The easiest way to install it, is to boot the mac mini into target disk mode (hold T on boot). Then connect a firewire cable to another system. The internal disk in the mini will now show up as a disk on this other system.<br />
<br />
create a 4GB NTFS primary partition.<br />
copy the contents of windows 10 x32 cdrom onto it<br />
make the partition active with diskpart (select disk X/select partion X/active)<br />
put a bootsector on it. from cdrom \boot\bootsect.exe /nt60 y:<br />
<br />
reboot mini, and it will install windows from the internal disk.<br />
<br />
thanks to <a href="https://www.bleepingcomputer.com/forums/t/619313/clean-install-windows-directly-from-the-hard-disk-drive/">https://www.bleepingcomputer.com/forums/t/619313/clean-install-windows-directly-from-the-hard-disk-drive/</a><br />
<br />
drivers are fun, get apple ir, bluetooth etc from <a href="https://support.apple.com/kb/DL1636?viewlocale=en_US&locale=en_US" target="_blank">bootcamp 4.0.4326</a> and extract the sigmatel audio drivers, and force install them as an 'update driver' 'have disk' action<br />
more here <a href="https://www.reddit.com/r/mac/comments/5dsvur/installation_of_win10_x64_on_2006_macbook21_2008/">https://www.reddit.com/r/mac/comments/5dsvur/installation_of_win10_x64_on_2006_macbook21_2008/</a></div>
Desrahttp://www.blogger.com/profile/10672334333562822105noreply@blogger.com0tag:blogger.com,1999:blog-4316697003523067161.post-45761368870898104362020-03-24T15:31:00.001-07:002020-10-26T10:32:26.681-07:00Installing FreeBSD 13 on a mac mini 2,1<div dir="ltr" style="text-align: left;" trbidi="on">
Mac mini 2,1 devices are tricky, they are 64bit, but have a 32bit EFI. booting a usb to install Freebsd isn't going to work.<br />
<br />
my internal cdrom drive is faulty, so can't use that<br />
an external cdrom won't install either.<br />
<br />
The easiest way to install it, is to boot the mac mini into target disk mode (hold T on boot). Then connect a fireware cable to another system. The internal disk in the mini will now show up as a disk on this other system.<br />
<br />
install virtualbox and setup raw disk access to the firewire drive. install freebsd in virtualbox, which is therefore writing at a raw level to the disk in the mini. complete the install, power cycle the mini and it should boot into freebsd.<br />
<br />
everything worked for me, graphics were a problem though with freebsd, it wouldn't detect the DVI. digging around, this fixed it<br />
<br />
installing port graphics/drm-fbsd12.0-kmod and adding </div><div dir="ltr" style="text-align: left;" trbidi="on"><span> </span> kld_list="/boot/modules/drm.ko /boot/modules/i915kms.ko" </div><div dir="ltr" style="text-align: left;" trbidi="on">to the top of rc.conf,
</div>
Desrahttp://www.blogger.com/profile/10672334333562822105noreply@blogger.com0tag:blogger.com,1999:blog-4316697003523067161.post-31215584938016306832019-11-12T01:20:00.006-08:002020-10-26T10:39:28.976-07:00Using Oracle Autonomous database with PHP<div dir="ltr" style="text-align: left;" trbidi="on">
The Oracle Cloud free tier is pretty generous, one thing that stands out is the free tier for a managed database. Normally I would use mysql , but this is oracle and I haven't used that in a long time. I also haven't used it with PHP<br />
<br />
These are my notes to make it work on ubuntu<br />
<br />
overview:<br />
1. download and install oracle client and sdk<br />
2. setup your wallet<br />
3. setup php<br />
4. test<br />
<br />
1. setup and install oracle stuff<br />
<br />
<pre><code class="sh">mkdir /opt/oracle
mkdir /opt/oracle
cd /opt/oracle
wget https://download.oracle.com/otn_software/linux/instantclient/193000/instantclient-basic-linux.x64-19.3.0.0.0dbru.zip
wget https://download.oracle.com/otn_software/linux/instantclient/193000/instantclient-sdk-linux.x64-19.3.0.0.0dbru.zip
unzip instantclient-basic-linux.x64*.zip
unzip instantclient-sdk-linux.x64-*.zip
echo /opt/oracle/instantclient_19_3 > /etc/ld.so.conf.d/oracle-instantclient
ldconfig
echo "LD_LIBRARY_PATH=/opt/oracle/instantclient_19_3:$LD_LIBRARY_PATH" >> /etc/enviroment
LD_LIBRARY_PATH=/opt/oracle/instantclient_19_3:$LD_LIBRARY_PATH
</code>
</pre>
<br />
2. setup wallet<br />
Download your wallet from the OCI database page<br />
<br />
<pre><code class="sh">cd /opt/oracle/instantclient_19_3/network/admin/
** get your wallet, put it here
unzip Wallet_DB*.zip
** shouldn't need this
export TNS_ADMIN=/opt/oracle/instantclient_19_3/network/admin
</code></pre>
<br />
3. setup php<br />
<pre><code class="sh">
apt-get install php-dev php-pear build-essential libaio1
pecl install oci8
**when asked use, instantclient,/opt/oracle/instantclient_19_3
echo "extension = oci8.so" >> /etc/php/7.2/cli/php.ini
</code></pre>
<br />
4. test<br />
use your ADMIN password or whatever creds. see you connection names in /opt/oracle/instantclient_19_3/network/admin/tnsnames.ora <br />
<br />
<pre><code class="php">
$conn = oci_connect("ADMIN", "password", "connection name from tnsnames", null, 0);
if ($conn) {
print "Success, connected!\n";
} else {
$m = oci_error();
echo $m['message'], "\n";
}
oci_close($conn);
</code></pre>
<br />
Thanks to <a href="https://gist.github.com/hewerthomn/81eea2935051eb2500941a9309bca703">https://gist.github.com/hewerthomn/81eea2935051eb2500941a9309bca703</a></div>
Desrahttp://www.blogger.com/profile/10672334333562822105noreply@blogger.com0tag:blogger.com,1999:blog-4316697003523067161.post-40313991179025216762019-07-01T10:23:00.001-07:002019-07-01T10:23:24.478-07:00<div dir="ltr" style="text-align: left;" trbidi="on">
Making SMS work with house alarm again.<br />
<br />
Some time ago, Eir ceased the SMS center feature, so house alarms couldn't send SMS's any more. to make things worse, they would try, and eventually time out.<br />
<br />
Asterisk can act as a service center for SMSs, so setting up a sipura ATA to take the call from the alarm panel , convert it to sip and send it to asterisks, ends up with the SMS sitting in /var/spool/asterisk/sms<br />
<br />
I used astlinux on an alix system as my asterisks setup, and added this to the extensions.conf<br />
<br />
<br />
exten => 1234/98765,1,Verbose(Receiving SMS from ${CALLERIDNUM})<br />
exten => 1234/98765,2,Answer<br />
exten => 1234/98765,3,Wait(1)<br />
exten => 1234/98765,4,SMS(sms_fixedline,as)<br />
exten => 1234/98765,5,Hangup<br />
<br />
and made sure the call was routed to this extension.<br />
<br />
you can simple cron watching the spool directory, pick the sms and forward via an sms provider with curl ...</div>
Desrahttp://www.blogger.com/profile/10672334333562822105noreply@blogger.com1tag:blogger.com,1999:blog-4316697003523067161.post-71487643999964652252019-03-19T18:18:00.001-07:002019-03-19T18:18:12.040-07:00Fire Alarms<div dir="ltr" style="text-align: left;" trbidi="on">
I recently had to find someone to service and install a fire alarm and security system. Came across <a href="https://www.nfss.ie/">https://www.nfss.ie</a> and they were excellent</div>
Desrahttp://www.blogger.com/profile/10672334333562822105noreply@blogger.com0tag:blogger.com,1999:blog-4316697003523067161.post-89561711825577334952018-11-29T16:23:00.001-08:002018-11-29T16:23:59.511-08:00Android Auto and Google maps 'GPS not found'<div dir="ltr" style="text-align: left;" trbidi="on">
I started using android Auto, and found that with my S8 , google maps would be inaccurate, and not update location, and display 'searching for gps' occasionally.<br />
<br />
This turns out to be the power saving feature enabled on the s8, it disables background location checks. Unfortunately disabling power saving makes me need to find a charger in the middle of the day, and I pretty much get through a full day without needing a charger.<br />
<br />
So, I looked at how I can remedy this situation and settled with using <a href="https://play.google.com/store/apps/details?id=com.llamalab.automate" target="_blank">Automate </a>to create a workflow, which is triggered when car-mode is enabled. This workflow then calls a tasker plugin called <a href="https://play.google.com/store/apps/details?id=com.balda.securetask" target="_blank">securetask</a>, which you grant special perms to. This plugin changes the power state , disabling power saving, so it fixes the problem. when car mode is exited, it turns powersaving back on.<br />
<br />
<br /></div>
Desrahttp://www.blogger.com/profile/10672334333562822105noreply@blogger.com0tag:blogger.com,1999:blog-4316697003523067161.post-70502861142589676742018-11-04T05:34:00.002-08:002018-11-29T16:26:06.196-08:00Hyundai Tuscon Radio, adding station logos<div dir="ltr" style="text-align: left;" trbidi="on">
get radiologos <a href="https://jkd.no-ip.biz/hyundai/radiologos/" target="_blank">here</a> and extract to an SD card<br />
<br />
then get the list of stations, and their PI from https://fmscan.org , generate the list for you country.<br />
<br />
each station has a PI, which is in hex, convert it to decimal, and rename the png logo file to sid_<decemial>.png<br />
<br />
do this for each station, and store it in the logos directory on the SD card<br />
<br />
insert the SD, start the unit, and select install from the menu that pops up.<br />
<br />
vw let you <a href="https://webspecial.volkswagen.de/vwinfotainment/de/de/index/downloads#/" target="_blank">download a zip</a> of your countries logos, but you still need to rename them<br />
<br /></div>
Desrahttp://www.blogger.com/profile/10672334333562822105noreply@blogger.com0tag:blogger.com,1999:blog-4316697003523067161.post-30752057350234907502018-09-23T13:33:00.003-07:002018-09-23T13:33:47.917-07:00figuring out s3 bucket size<div dir="ltr" style="text-align: left;" trbidi="on">
You can calculate the size of your buckets with commandline tools, or using the analytics feature. However, all of these incur charges.<br />
<br />
Alternatively you can run a '<a href="https://portal.aws.amazon.com/gp/aws/developer/account?ie=UTF8&action=usage-report" target="_blank">usage report</a>', save it as a csv , and then do some math<br />
<br />
<span style="font-family: Courier New, Courier, monospace;"><b><span style="background-color: white; font-size: 15.3px; white-space: pre-wrap;">cat report.csv | awk -F, </span><span class="hljs-string" style="background-color: white; box-sizing: border-box; color: #880000; font-size: 15.3px; white-space: pre-wrap;">'{printf "%.2f GB %s %s \n", $7/(1024**3 )/24, $4, $2}'</span><span style="background-color: white; font-size: 15.3px; white-space: pre-wrap;"> | </span><span class="hljs-keyword" style="background-color: white; box-sizing: border-box; font-size: 15.3px; white-space: pre-wrap;">sort</span><span style="background-color: white; font-size: 15.3px; white-space: pre-wrap;"> -n</span></b></span><br />
<span style="background-color: white; font-family: Inconsolata, monospace; font-size: 15.3px; white-space: pre-wrap;"><br /></span>
<br />
<br />
<br /></div>
Desrahttp://www.blogger.com/profile/10672334333562822105noreply@blogger.com0tag:blogger.com,1999:blog-4316697003523067161.post-84037258737583706642018-08-28T03:06:00.001-07:002018-08-28T03:09:41.248-07:00<div dir="ltr" style="text-align: left;" trbidi="on">
<span style="font-family: "trebuchet ms" , sans-serif;">Time to talk about google app engine, flex , standard , php, and google cloud storage.</span><br />
<span style="font-family: "trebuchet ms" , sans-serif;"><br /></span>
<span style="font-family: "trebuchet ms" , sans-serif;">I've been doing some experimenting using GAE to make a service like cloudinary. It's pretty simple to do, using imagick, which is installed in GAE. But here are some simple discoveries;</span><br />
<span style="font-family: "trebuchet ms" , sans-serif;"><br /></span>
<span style="font-family: "trebuchet ms" , sans-serif;">1) GAE flex, sounds like GAE standard, but it's not. if using php55 it's quite different. with php72 now launched in standard, it's closer to flex, you need a front_controller, and your app.yaml is simpler</span><br />
<span style="font-family: "trebuchet ms" , sans-serif;">2) GAE standard scales really quickly, like to 10k instances in 1 to 2 mins. Flex takes a LOT longer, think 30 mins</span><br />
<span style="font-family: "trebuchet ms" , sans-serif;">3) GAE can use imagick, imagick is not fast, and cpu intensive , fetching an image from a GCS bucket and rendering it cropped or resized is a 1-2 second operation.</span><br />
<span style="font-family: "trebuchet ms" , sans-serif;"><br /></span>
<span style="font-family: "trebuchet ms" , sans-serif;">you could use appengines image api, but for php it's limited to getservingurl functions. unless you want to write protobuf interfaces .</span><br />
<span style="font-family: "trebuchet ms" , sans-serif;"><br /></span>
<span style="font-family: "trebuchet ms" , sans-serif;">In python, it's way more useful, you can do all the usual transforms, and it's not cpu intensive on your appengine instance, meaning you don't scale to 10k instances. However it's not as fast as GCE , as below</span><br />
<span style="font-family: "trebuchet ms" , sans-serif;"><br /></span>
<span style="font-family: "trebuchet ms" , sans-serif;">So instead, I used GCE because</span><br />
<span style="font-family: "trebuchet ms" , sans-serif;"><br /></span>
<span style="font-family: "trebuchet ms" , sans-serif;">1) you can use libvips instead of imagick, 400ms for image resizing and serving, compared to 1-2 seconds with GAE, or 800ms with GAE and image api</span><br />
<span style="font-family: "trebuchet ms" , sans-serif;">2) you can use preemptible instances </span><br />
<span style="font-family: "trebuchet ms" , sans-serif;"><br /></span>
<span style="font-family: "trebuchet ms" , sans-serif;">The savings are huge, for my estimates, $400k + per year between GAE and GCE</span><br />
<span style="font-family: "trebuchet ms" , sans-serif;"><br /></span>
<span style="font-family: "trebuchet ms" , sans-serif;">two other findings, about php and the google wrappers; they are cool, you can do things like</span><br />
<span style="font-family: "trebuchet ms" , sans-serif;"><br /></span>
<span style="font-family: "trebuchet ms" , sans-serif;">if (file_exists("gs://bucket/foo/bar"))</span><br />
<span style="font-family: "trebuchet ms" , sans-serif;"><br /></span>
<span style="font-family: "trebuchet ms" , sans-serif;">which is cool, right ? , not really, when you dig in. under the hood, that does two bucket calls. because it tests if it's writable, even if your operation doesn't care about writes. It's more efficient to use curl, and test the contents returned etc, and then use the contents later in you code. This becomes more apparent (it did for me) when using a GLB, with nodes around the world. users hitting nodes in Australia hitting a multi-region bucket in the US, were a low slower, than the same users hitting a node in the US. This is due to the multiple transcontinental bucket calls. using curl and a single call eliminated the performance differences</span></div>
Desrahttp://www.blogger.com/profile/10672334333562822105noreply@blogger.com0tag:blogger.com,1999:blog-4316697003523067161.post-5360052155582953052018-05-21T07:08:00.000-07:002018-05-21T07:08:15.865-07:00load testing<div dir="ltr" style="text-align: left;" trbidi="on">
I have used apache bench, and more recently artillery.io tools, but it still wasn't ideal. I came across this tool which will do a better job for basic testing https://github.com/wg/wrk</div>
Desrahttp://www.blogger.com/profile/10672334333562822105noreply@blogger.com0tag:blogger.com,1999:blog-4316697003523067161.post-25433148059827777792018-03-29T09:33:00.001-07:002018-03-29T09:33:07.783-07:00Sky Q tuning with a Meter<div dir="ltr" style="text-align: left;" trbidi="on">
Using a sky Q compatible LNB, you can still tune with a regular digital tuner. The analogue inline tuners won't get enough voltage to work right.<br />
<br />
I use a satlink ws-6933, and set it to a vertical transponder and hooked it to the vertical output of the LNB, without doing that you will get a signal measurement with no quality measurement<br />
<br />
Below are the screen shots of sky Q signal on the meter and in the sky Q UI too.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgaItZm2LPRiIjrW1_rrFl11oEJdNDoBH9JpoOhD8g01gc8ujkFcQpNLSMVhB2EImtjc4cleZvB5Sp8tqtxnCdWylJmm9QESNRkoG4aK_3TeJ9MSdY7NzRhwzG23yIpfk3-GlDsmLzh4S0/s1600/skyq+signal+from+skyq+box.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="716" data-original-width="1293" height="177" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgaItZm2LPRiIjrW1_rrFl11oEJdNDoBH9JpoOhD8g01gc8ujkFcQpNLSMVhB2EImtjc4cleZvB5Sp8tqtxnCdWylJmm9QESNRkoG4aK_3TeJ9MSdY7NzRhwzG23yIpfk3-GlDsmLzh4S0/s320/skyq+signal+from+skyq+box.jpg" width="320" /></a></div>
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhUMlWl_bwisOd9iK8OScRZTfzGXz7cxKxoPfg_EcHUFzqILTsFNH0VSDmG-yAhha5hzzsP2hBbMqq9GsOuWGgzzJVCKcdk8OiLFRX74A3MxOVvfbFiBGZeMntQ0Po04I94DWn3UrpaWEg/s1600/skyq+signal.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="717" data-original-width="1475" height="155" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhUMlWl_bwisOd9iK8OScRZTfzGXz7cxKxoPfg_EcHUFzqILTsFNH0VSDmG-yAhha5hzzsP2hBbMqq9GsOuWGgzzJVCKcdk8OiLFRX74A3MxOVvfbFiBGZeMntQ0Po04I94DWn3UrpaWEg/s320/skyq+signal.jpg" width="320" /></a></div>
<br /></div>
Desrahttp://www.blogger.com/profile/10672334333562822105noreply@blogger.com0tag:blogger.com,1999:blog-4316697003523067161.post-10339651044870173732018-01-31T13:48:00.001-08:002018-01-31T14:02:40.225-08:00FreeBSD in GCE<div dir="ltr" style="text-align: left;" trbidi="on">
Yes there are supported images of amd64 freebsd available in GCE to boot, but I needed an i386 variant so here are the steps I took.<br />
<br />
<br />
I downloaded the mini memstick image, converted it to a disk format virtualbox recognised<br />
<br />
<span style="font-family: "courier new" , "courier" , monospace;">VBoxManage.exe convertfromraw FreeBSD-11.1-RELEASE-amd64-mini-memstick.img FreeBSD-11.1-RELEASE-amd64-mini-memstick.vdi --format vdi</span><br />
<br />
Then made a virtual machine with that as it's disk, booted and chose the shell option, then remounted as read/write, and put this into /boot/loader.conf<br />
<span style="font-family: "courier new" , "courier" , monospace;"><br /></span>
<span style="font-family: "courier new" , "courier" , monospace;">mount -o rw /dev/ufs/FreeBSD_install /</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"><br /></span>
<span style="font-family: "courier new" , "courier" , monospace;">boot_multicons="YES"</span><br />
<span style="font-family: "courier new" , "courier" , monospace;">boot_serial="YES"</span><br />
<span style="font-family: "courier new" , "courier" , monospace;">comconsole_speed="115200"</span><br />
<span style="font-family: "courier new" , "courier" , monospace;">console="comconsole,vidconsole"</span><br />
<br />
then shutdown the machine (gracefully!)<br />
<br />
now I have an image that supports install via a serial port, just need to make it the right format for GCE to consider as a boot disk<br />
<br />
<span style="font-family: Courier New, Courier, monospace;">VBoxManage.exe clonehd FreeBSD-11.1-RELEASE-amd64-mini-memstick.vdi disk.raw --format raw</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"><br /></span>
<span style="font-family: "courier new" , "courier" , monospace;">tar -Sczf /tmp/compressed-image.tar.gz disk.raw</span><br />
<br />
now put compressed-image.tar.gz in a bucket and create an image from it.<br />
<br />
create a virtual machine with this as the primary disk and a 20GB second disk. Boot , and connect serial port , and install to the second disk. before finishing the install make sure you update fstab on the second disk, so it can be used as a primary disk.<br />
<br />
lastly fixup your nic MTU<br />
<br />
<span style="font-family: "courier new" , "courier" , monospace;">ifconfig_vtnet0="SYNCDHCP mtu 1460"</span><br />
<div>
<br /></div>
<br /></div>
Desrahttp://www.blogger.com/profile/10672334333562822105noreply@blogger.com0tag:blogger.com,1999:blog-4316697003523067161.post-76454466605632664202017-11-30T13:45:00.000-08:002017-11-30T13:52:16.524-08:00Controlling an LG soundbar<div dir="ltr" style="text-align: left;" trbidi="on">
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">As part of my home automation configuration, I wanted to figure out how to control my soundbar.</span><br />
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><br /></span>
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">Seems it's not documented, there isn't an API, but there is an Android App. So I installed Genymotion, set the nic to be bridged and used wireshark to sniff what the app was doing. I saw udp packets for each key, so copied the data, and used it like this....</span><br />
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><br /></span>
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">Mute: 080312002a0808011204081a1002 followed by 080312002a0808011204081a1001 </span><br />
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">Vol down: 080312002a080801120408191002 then 080312002a080801120408191001</span><br />
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">Vol up: 080312002a080801120408181002 then 080312002a080801120408181001</span><br />
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">Power off: 080312002a080801120408011002 then 080312002a080801120408011001 </span><br />
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">switching inputs (optical/bluetooth/home): 080312002a0808011204084d1002 then 080312002a0808011204084d1001</span><br />
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><br /></span>
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">So, to send this udp data to a sound bar at 1.2.3.4 address </span><br />
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><br /></span>
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">echo "080312002a080801120408011002" | xxd -r -p > /dev/udp/1.2.3.4/9741 </span><br />
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><br /></span>
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">netcat seemed quite slow for some reason</span></div>
Desrahttp://www.blogger.com/profile/10672334333562822105noreply@blogger.com1tag:blogger.com,1999:blog-4316697003523067161.post-75896473393422164132017-11-21T03:54:00.001-08:002017-11-21T03:54:21.524-08:00caching a webcam<div dir="ltr" style="text-align: left;" trbidi="on">
I Recently tried to use a webcam on the internet and it was unusable because too many people were using it.<br />
<br />
Taking a peek, it was clear it was simple jpgs being refreshed by client side JS , using the built in webui in the camera itself, the hardware just couldn't handle too many users.<br />
<br />
So I setup some urls and cloudfront to cache, and then an nginx proxy which would do the right thing with headers to make the images cache friendly. Then reached out to the webmaster and talked them through what to do<br />
<br />
Next step is to consider changing the client JS to not just increment a number in the url, which is ignored by the CDN, but maybe find some other way to cache to you get better than one frame a second.<br />
<br />
<br />
<span style="font-family: Courier New, Courier, monospace; font-size: x-small;">server {</span><br />
<span style="font-family: Courier New, Courier, monospace; font-size: x-small;">listen 8888;</span><br />
<span style="font-family: Courier New, Courier, monospace; font-size: x-small;"><br /></span>
<span style="font-family: Courier New, Courier, monospace; font-size: x-small;">access_log /var/log/nginx/cam1.access.log;</span><br />
<span style="font-family: Courier New, Courier, monospace; font-size: x-small;">error_log /var/log/nginx/cam1.error.log;</span><br />
<span style="font-family: Courier New, Courier, monospace; font-size: x-small;"><br /></span>
<span style="font-family: Courier New, Courier, monospace; font-size: x-small;">server_name cam1.test.com;</span><br />
<span style="font-family: Courier New, Courier, monospace; font-size: x-small;">location / {</span><br />
<span style="font-family: Courier New, Courier, monospace; font-size: x-small;"><br /></span>
<span style="font-family: Courier New, Courier, monospace; font-size: x-small;"> add_header Pragma public;</span><br />
<span style="font-family: Courier New, Courier, monospace; font-size: x-small;"> add_header Cache-Control "public,max-age=1,s-max-age=1";</span><br />
<span style="font-family: Courier New, Courier, monospace; font-size: x-small;"><br /></span>
<span style="font-family: Courier New, Courier, monospace; font-size: x-small;"> proxy_pass http://1.2.3.4:120/;</span><br />
<span style="font-family: Courier New, Courier, monospace; font-size: x-small;"> proxy_set_header Host 1.2.3.4;</span><br />
<span style="font-family: Courier New, Courier, monospace; font-size: x-small;">}</span><br />
<span style="font-family: Courier New, Courier, monospace; font-size: x-small;"><br /></span>
<span style="font-family: Courier New, Courier, monospace; font-size: x-small;">}</span><br />
<span style="font-family: Courier New, Courier, monospace; font-size: x-small;"><br /></span>
<span style="font-family: Courier New, Courier, monospace; font-size: x-small;"><br /></span>
<span style="font-family: Courier New, Courier, monospace; font-size: x-small;">server {</span><br />
<span style="font-family: Courier New, Courier, monospace; font-size: x-small;">listen 8888;</span><br />
<span style="font-family: Courier New, Courier, monospace; font-size: x-small;"><br /></span>
<span style="font-family: Courier New, Courier, monospace; font-size: x-small;">access_log /var/log/nginx/cam2.access.log;</span><br />
<span style="font-family: Courier New, Courier, monospace; font-size: x-small;">error_log /var/log/nginx/cam2.error.log;</span><br />
<span style="font-family: Courier New, Courier, monospace; font-size: x-small;"><br /></span>
<span style="font-family: Courier New, Courier, monospace; font-size: x-small;">server_name cam2.test.com;</span><br />
<span style="font-family: Courier New, Courier, monospace; font-size: x-small;">location / {</span><br />
<span style="font-family: Courier New, Courier, monospace; font-size: x-small;"><br /></span>
<span style="font-family: Courier New, Courier, monospace; font-size: x-small;"> add_header max-age 1;</span><br />
<span style="font-family: Courier New, Courier, monospace; font-size: x-small;"> add_header s-max-age 1;</span><br />
<span style="font-family: Courier New, Courier, monospace; font-size: x-small;"> add_header Pragma public;</span><br />
<span style="font-family: Courier New, Courier, monospace; font-size: x-small;"> add_header Cache-Control "public";</span><br />
<span style="font-family: Courier New, Courier, monospace; font-size: x-small;"> proxy_pass http://1.2.3.4:121/;</span><br />
<span style="font-family: Courier New, Courier, monospace; font-size: x-small;"> proxy_set_header Host 1.2.3.4;</span><br />
<span style="font-family: Courier New, Courier, monospace; font-size: x-small;">}</span><br />
<span style="font-family: Courier New, Courier, monospace; font-size: x-small;"><br /></span>
<span style="font-family: Courier New, Courier, monospace; font-size: x-small;">}</span><br />
<span style="font-family: Courier New, Courier, monospace; font-size: x-small;"><br /></span>
<span style="font-family: Courier New, Courier, monospace; font-size: x-small;">server {</span><br />
<span style="font-family: Courier New, Courier, monospace; font-size: x-small;">listen 8888;</span><br />
<span style="font-family: Courier New, Courier, monospace; font-size: x-small;"><br /></span>
<span style="font-family: Courier New, Courier, monospace; font-size: x-small;">access_log /var/log/nginx/cam3.access.log;</span><br />
<span style="font-family: Courier New, Courier, monospace; font-size: x-small;">error_log /var/log/nginx/cam3.error.log;</span><br />
<span style="font-family: Courier New, Courier, monospace; font-size: x-small;"><br /></span>
<span style="font-family: Courier New, Courier, monospace; font-size: x-small;">server_name cam3.test.com;</span><br />
<span style="font-family: Courier New, Courier, monospace; font-size: x-small;">location / {</span><br />
<span style="font-family: Courier New, Courier, monospace; font-size: x-small;"><br /></span>
<span style="font-family: Courier New, Courier, monospace; font-size: x-small;"> add_header max-age 1;</span><br />
<span style="font-family: Courier New, Courier, monospace; font-size: x-small;"> add_header s-max-age 1;</span><br />
<span style="font-family: Courier New, Courier, monospace; font-size: x-small;"> add_header Pragma public;</span><br />
<span style="font-family: Courier New, Courier, monospace; font-size: x-small;"> add_header Cache-Control "public";</span><br />
<span style="font-family: Courier New, Courier, monospace; font-size: x-small;"> proxy_pass http://1.2.3.4:122/;</span><br />
<span style="font-family: Courier New, Courier, monospace; font-size: x-small;"> proxy_set_header Host 1.2.3.4;</span><br />
<span style="font-family: Courier New, Courier, monospace; font-size: x-small;">}</span><br />
<span style="font-family: Courier New, Courier, monospace; font-size: x-small;">}</span><br />
</div>
Desrahttp://www.blogger.com/profile/10672334333562822105noreply@blogger.com1tag:blogger.com,1999:blog-4316697003523067161.post-58523675217654812802017-11-12T14:28:00.000-08:002017-11-12T14:29:29.956-08:00home automation, alexa and an LG lm660 series tv, cctv and more<div dir="ltr" style="text-align: left;" trbidi="on">
<span style="font-family: "arial" , "helvetica" , sans-serif;">I thought I'd try alexa, and so it began ....</span><br />
<span style="font-family: "arial" , "helvetica" , sans-serif;"><br /></span>
<span style="font-family: "arial" , "helvetica" , sans-serif;">Alexa (unlike google home) talks over your LAN to philips HUE devices, so you can simply setup a fake hue bridge to interface with alexa. this is much easier than the official lambda foo you have to do in aws.</span><br />
<span style="font-family: "arial" , "helvetica" , sans-serif;"><br /></span>
<span style="font-family: "arial" , "helvetica" , sans-serif;">I also had <a href="http://domoticz.com/" target="_blank">domoticz</a> setup, tracking my solar usage, electrical usage, and Nest data. </span><br />
<span style="font-family: "arial" , "helvetica" , sans-serif;"><br /></span>
<span style="font-family: "arial" , "helvetica" , sans-serif;">So, using <a href="https://github.com/bwssytems/ha-bridge" target="_blank">habridge</a> I ended up connecting habridge to domoticz, but will probably remove that integration, and just do habridge direct to my scripts.</span><br />
<span style="font-family: "arial" , "helvetica" , sans-serif;"><br /></span>
<span style="font-family: "arial" , "helvetica" , sans-serif;">in domoticz I setup virtual switches that ran scripts, so habridge saw these switches and presented them like hue lights to alexa, so I can say things like 'alexa turn on sky tv' , or 'alexa turn on netflix'</span><br />
<span style="font-family: "arial" , "helvetica" , sans-serif;"><br /></span>
<span style="font-family: "arial" , "helvetica" , sans-serif;">My two interesting problems were 1) how to turn on my tv, as it doesn't have WOL, and 2) how to handle CCTV (not really alexa related)</span><br />
<span style="font-family: "arial" , "helvetica" , sans-serif;"><br /></span>
<span style="font-family: "arial" , "helvetica" , sans-serif;">My tv is an LG lm660t , which doesn't have WOL, so looked at solutions to use infra red to turn it on, but it all felt pretty flaky. I got a raspberry PI , and hooked it up to a hdmi port, and turned on simpllink in the LG, so I could now run a commandline <a href="https://github.com/Pulse-Eight/libcec" target="_blank">tool</a> on the pi, to tell the tv to wake up via the hdmi port. This tool became a script behind a virtual switch on domoticz.</span><br />
<span style="font-family: "arial" , "helvetica" , sans-serif;"><br /></span>
<span style="font-family: "arial" , "helvetica" , sans-serif;">This was pretty cool, but as my tv had netflix and medialink / plex apps installed, I wanted to be able to make them run too, I extended https://github.com/SteveWinfield/PHP-LG-SmartTV to send those commands following the <a href="http://developer.lgappstv.com/TV_HELP/topic/lge.tvsdk.references.book/html/UDAP/UDAP/Launch%20Application%20Controller%20Host.htm?path=4_0_1_4_1_0#_Toc353804454" target="_blank">dev docs</a></span><br />
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><br /></span>
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">now I could turn on the tv via the pi, then signal the tv to launch and app, or turn off the tv.</span><br />
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><br /></span>
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">I also hooked up sky tv via this <a href="https://github.com/dalhundal/sky-remote" target="_blank">tool</a> , so I could control it via IP </span><br />
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><br /></span>
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">that left me with one last job , hooking up cctv, I wanted to be able to view my annke streams which are 1080p mp4 rtsp streams, and thought about plex, but ended up just using the pi, as all it would take was switching the input, no lag or boot times etc.</span><br />
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><br /></span>
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">I endedup using <a href="https://github.com/SvenVD/rpisurv" target="_blank">this</a> to do it, but had to override some settings to make it work just right on my tv. I got lines and sync problems and all kinds of weird things until I put these lines in /boot/config.txt</span><br />
<span style="font-size: x-small;"><br /></span>
<span style="color: #76a5af; font-family: "courier new" , "courier" , monospace; font-size: x-small;">hdmi_force_hotplug=1</span><br />
<span style="color: #76a5af; font-family: "courier new" , "courier" , monospace; font-size: x-small;">hdmi_group=1</span><br />
<br />
<span style="color: #76a5af; font-family: "courier new" , "courier" , monospace; font-size: x-small;">hdmi_mode=33</span><br />
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><br /></span>
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">then it was all good</span><br />
<div>
<br /></div>
<div>
<br /></div>
</div>
Desrahttp://www.blogger.com/profile/10672334333562822105noreply@blogger.com0tag:blogger.com,1999:blog-4316697003523067161.post-15458617675420633942017-11-12T13:58:00.003-08:002017-11-12T14:34:57.459-08:00using t1n1wall, opnsense or pfsense on Google Compute Engine GCE<div dir="ltr" style="text-align: left;" trbidi="on">
<span style="font-family: "arial" , "helvetica" , sans-serif;">I have been doing some work in GCP recently, both appengine , and GCE. We wanted to make sure all our instances were on private ips and only the LBs had internet ips.</span><br />
<span style="font-family: "arial" , "helvetica" , sans-serif;"><br /></span>
<span style="font-family: "arial" , "helvetica" , sans-serif;">This gave us the problem of how to allow our instances reach the internet for updates or for api calls outside.</span><br />
<span style="font-family: "arial" , "helvetica" , sans-serif;"><br /></span>
<span style="font-family: "arial" , "helvetica" , sans-serif;">In AWS you had a NAT gateway, but in GCP this doesn't exist. So I set about looking at the easiest way to do NAT from a private IP subnet to a Public address. I am very familiar with m0n0wall and t1n1wall and a tiny bit with pfsense and less with opnsense.</span><br />
<span style="font-family: "arial" , "helvetica" , sans-serif;"><br /></span>
<span style="font-family: "arial" , "helvetica" , sans-serif;">The tl;dr is that all these distributions ship an image which within the distribution there is a disk image. Taking this internal image, renaming it and re-compressing it is all you need to do to get it working in GCE. you can configure it via the serial port using <a href="https://cloud.google.com/compute/docs/instances/interacting-with-serial-console" target="_blank">these</a> instructions</span><br />
<span style="font-family: "arial" , "helvetica" , sans-serif;"><br /></span>
<span style="font-family: "arial" , "helvetica" , sans-serif;"><br /></span>
<span style="font-family: "arial" , "helvetica" , sans-serif;"> There are guides out there around doing things with Linux and stuff, but you can skip that step.</span><br />
<span style="font-family: "arial" , "helvetica" , sans-serif;"><br /></span>
<span style="font-family: "arial" , "helvetica" , sans-serif;">I took the latest version of t1n1wall 2.11 , got the simple amd64 serial version and </span><br />
<span style="color: #76a5af; font-family: "arial" , "helvetica" , sans-serif;"><br /></span>
<span style="color: #76a5af; font-family: "courier new" , "courier" , monospace; font-size: xx-small;">1) decompressed it</span><br />
<span style="color: #76a5af; font-family: "courier new" , "courier" , monospace; font-size: xx-small;">2) renamed image.bin to disk.raw</span><br />
<span style="color: #76a5af; font-family: "courier new" , "courier" , monospace; font-size: xx-small;">3) recompressed it to a tar.gz (see <a href="https://cloud.google.com/compute/docs/images/import-existing-image#create_image_file" target="_blank">here</a>)</span><br />
<span style="color: #76a5af; font-family: "courier new" , "courier" , monospace; font-size: xx-small;">4) Copy to a google bucket</span><br />
<span style="color: #76a5af; font-family: "courier new" , "courier" , monospace; font-size: xx-small;">5) in GCE -> Images, create a new image from that file in a bucket</span><br />
<span style="color: #76a5af; font-family: "courier new" , "courier" , monospace; font-size: xx-small;">6) create an instance from that new image , configure networks, boot and configure via serial port</span><br />
<span style="font-family: "arial" , "helvetica" , sans-serif;"><br /></span>
<span style="font-family: "arial" , "helvetica" , sans-serif;">For pfsense, it's a bit more complex, as the image you boot is an installer image, that expects to install to a disk, so when making the instance, add a second disk, then install to it, then make an image of that disk</span><br />
<span style="font-family: "arial" , "helvetica" , sans-serif;"><br /></span>
<span style="font-family: "arial" , "helvetica" , sans-serif;">For opnsense, use the nano image as it's a live image, not an installer</span><br />
<span style="font-family: "arial" , "helvetica" , sans-serif;"><br /></span>
<span style="font-family: "arial" , "helvetica" , sans-serif;">Voila ! I prefer t1n1wall for this as it's so simple, and runs on cheaper virts better.</span></div>
Desrahttp://www.blogger.com/profile/10672334333562822105noreply@blogger.com2tag:blogger.com,1999:blog-4316697003523067161.post-69116915931625645012017-06-12T04:18:00.003-07:002017-06-12T04:18:53.946-07:00Debugging with Curl<div dir="ltr" style="text-align: left;" trbidi="on">
For years I used --header "host: foo.bar" to make curl do the right thing when testing.<br />
<br />
Turns out there is a better way<br />
<br />
curl -svo /dev/null https://www.foo.bar --resolve www.foo.bar:443:127.0.0.1</div>
Desrahttp://www.blogger.com/profile/10672334333562822105noreply@blogger.com0tag:blogger.com,1999:blog-4316697003523067161.post-31344509304495262342016-08-29T02:57:00.000-07:002017-11-12T14:00:24.737-08:00<div dir="ltr" style="text-align: left;" trbidi="on">
<span style="font-family: Helvetica Neue, Arial, Helvetica, sans-serif;">I recently faced dealing with some badbots and scrapers, it was in a LAMP stack with varnish at the edge. I decided to deal with it in varnish, as I always try handle as many tasks at the edge as I can, and leave apache to serve php.</span><br />
<span style="font-family: Helvetica Neue, Arial, Helvetica, sans-serif;"><br /></span>
<span style="font-family: Helvetica Neue, Arial, Helvetica, sans-serif;">So, I thought about the problem a bit, and decided to use a token bucket, nothing unusual about that. (I had to modify the source to allow passing values instead of defaulting to 1 token). However I went a bit further and decided that different pages are 'worth' more than others, i.e. they are more sensitive. For example, accessing the homepage vs accessing account pages. This required a patch of the throttle mod to allow you to pass the 'cost' of a page, so more than 1 token is removed from the bucket. For now it just logs, but I intend to send a user that is exceeding the request rate to a different backend server that will give them fake data to devalue their scraping.</span><br />
<span style="font-family: Helvetica Neue, Arial, Helvetica, sans-serif;"><br /></span>
<span style="font-family: Helvetica Neue, Arial, Helvetica, sans-serif;">you could detect user agent strings or other patterns and use as a multiplier , so bad user agent will multiply the tokens to be removed by say 5. you could do the same with cookies too.</span><br />
<span style="font-family: Helvetica Neue, Arial, Helvetica, sans-serif;"><br /></span>
<span style="font-family: Helvetica Neue, Arial, Helvetica, sans-serif;">sample config below</span><br />
<span style="font-family: Helvetica Neue, Arial, Helvetica, sans-serif;"><br /></span>
<span style="color: #76a5af; font-family: Courier New, Courier, monospace; font-size: x-small;">vcl 4.0;</span><br />
<span style="color: #76a5af; font-family: Courier New, Courier, monospace; font-size: x-small;">import var;</span><br />
<span style="color: #76a5af; font-family: Courier New, Courier, monospace; font-size: x-small;">import vsthrottle;</span><br />
<span style="color: #76a5af; font-family: Courier New, Courier, monospace; font-size: x-small;">import std;</span><br />
<span style="color: #76a5af; font-family: Courier New, Courier, monospace; font-size: x-small;"><br /></span>
<span style="color: #76a5af; font-family: Courier New, Courier, monospace; font-size: x-small;"><br /></span>
<span style="color: #76a5af; font-family: Courier New, Courier, monospace; font-size: x-small;"># Default backend definition. Set this to point to your content server.</span><br />
<span style="color: #76a5af; font-family: Courier New, Courier, monospace; font-size: x-small;">backend default {</span><br />
<span style="color: #76a5af; font-family: Courier New, Courier, monospace; font-size: x-small;"> .host = "127.0.0.1";</span><br />
<span style="color: #76a5af; font-family: Courier New, Courier, monospace; font-size: x-small;"> .port = "8080";</span><br />
<span style="color: #76a5af; font-family: Courier New, Courier, monospace; font-size: x-small;">}</span><br />
<span style="color: #76a5af; font-family: Courier New, Courier, monospace; font-size: x-small;"><br /></span>
<span style="color: #76a5af; font-family: Courier New, Courier, monospace; font-size: x-small;">sub vcl_recv {</span><br />
<span style="color: #76a5af; font-family: Courier New, Courier, monospace; font-size: x-small;"><br /></span>
<span style="color: #76a5af; font-family: Courier New, Courier, monospace; font-size: x-small;"> # set weights on pages using regex patterns</span><br />
<span class="Apple-tab-span" style="color: #76a5af; font-family: Courier New, Courier, monospace; font-size: x-small; white-space: pre;"> </span><br />
<span style="color: #76a5af; font-family: Courier New, Courier, monospace; font-size: x-small;"><span class="Apple-tab-span" style="white-space: pre;"> </span>var.set_int("sensitivity", 1);</span><br />
<span style="color: #76a5af; font-family: Courier New, Courier, monospace; font-size: x-small;"> </span><br />
<span style="color: #76a5af; font-family: Courier New, Courier, monospace; font-size: x-small;"> if (req.url ~ "^/browse/?") {</span><br />
<span style="color: #76a5af; font-family: Courier New, Courier, monospace; font-size: x-small;"> var.set_int("sensitivity", 10);</span><br />
<span style="color: #76a5af; font-family: Courier New, Courier, monospace; font-size: x-small;"> } elsif (req.url ~ "^/stats/?") {</span><br />
<span style="color: #76a5af; font-family: Courier New, Courier, monospace; font-size: x-small;"> var.set_int("sensitivity", 20);</span><br />
<span style="color: #76a5af; font-family: Courier New, Courier, monospace; font-size: x-small;"> } elsif (req.url ~ "^/account/?") {</span><br />
<span style="color: #76a5af; font-family: Courier New, Courier, monospace; font-size: x-small;"> var.set_int("sensitivity", 30);</span><br />
<span style="color: #76a5af; font-family: Courier New, Courier, monospace; font-size: x-small;"> }</span><br />
<span style="color: #76a5af; font-family: Courier New, Courier, monospace; font-size: x-small;"><br /></span>
<span style="color: #76a5af; font-family: Courier New, Courier, monospace; font-size: x-small;"> # now, lets see if they have enough credit in their token bucket to ask for this page</span><br />
<span style="color: #76a5af; font-family: Courier New, Courier, monospace; font-size: x-small;"> # token bucket is set to 150 tokens, and is measured for 10 seconds</span><br />
<span style="color: #76a5af; font-family: Courier New, Courier, monospace; font-size: x-small;"><br /></span>
<span style="color: #76a5af; font-family: Courier New, Courier, monospace; font-size: x-small;"> if (vsthrottle.is_denied(client.identity, var.get_int("sensitivity") , 150, 10s)) {</span><br />
<span style="color: #76a5af; font-family: Courier New, Courier, monospace; font-size: x-small;"><br /></span>
<span style="color: #76a5af; font-family: Courier New, Courier, monospace; font-size: x-small;"> <span class="Apple-tab-span" style="white-space: pre;"> </span># Client has exceeded credit limit, lets do things like;</span><br />
<span style="color: #76a5af; font-family: Courier New, Courier, monospace; font-size: x-small;"><span class="Apple-tab-span" style="white-space: pre;"> </span># set req.backend = fakedataserver;</span><br />
<span style="color: #76a5af; font-family: Courier New, Courier, monospace; font-size: x-small;"><span class="Apple-tab-span" style="white-space: pre;"> </span># maybe set a http header into the get request to add to apache logs ?</span><br />
<span style="color: #76a5af; font-family: Courier New, Courier, monospace; font-size: x-small;"><span class="Apple-tab-span" style="white-space: pre;"> </span>std.syslog(180, "RECV: " + req.http.host + req.url+ client.identity);</span><br />
<span style="color: #76a5af; font-family: Courier New, Courier, monospace; font-size: x-small;"><span class="Apple-tab-span" style="white-space: pre;"> </span>return (synth(429, "Too Many Requests"));</span><br />
<span style="color: #76a5af; font-family: Courier New, Courier, monospace; font-size: x-small;"> }</span><br />
<span style="color: #76a5af; font-family: Courier New, Courier, monospace; font-size: x-small;"><br /></span>
<span style="color: #76a5af; font-family: Courier New, Courier, monospace; font-size: x-small;">}</span><br />
<span style="color: #76a5af; font-family: Courier New, Courier, monospace; font-size: x-small;"><br /></span>
<span style="color: #76a5af; font-family: Courier New, Courier, monospace; font-size: x-small;">sub vcl_backend_response {</span><br />
<span style="color: #76a5af; font-family: Courier New, Courier, monospace; font-size: x-small;">}</span><br />
<span style="color: #76a5af; font-family: Courier New, Courier, monospace; font-size: x-small;"><br /></span>
<span style="color: #76a5af; font-family: Courier New, Courier, monospace; font-size: x-small;">sub vcl_deliver {</span><br />
<span style="color: #76a5af; font-family: Courier New, Courier, monospace; font-size: x-small;">}</span></div>
Desrahttp://www.blogger.com/profile/10672334333562822105noreply@blogger.com0