<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0"><channel><title><![CDATA[Daneke Blog]]></title><description><![CDATA[Web Developer]]></description><link>https://blog.daneke.ge</link><generator>RSS for Node</generator><lastBuildDate>Thu, 16 Apr 2026 07:50:43 GMT</lastBuildDate><atom:link href="https://blog.daneke.ge/rss.xml" rel="self" type="application/rss+xml"/><language><![CDATA[en]]></language><ttl>60</ttl><item><title><![CDATA[Hidemail.app + Bitwarden]]></title><description><![CDATA[You want to generate HideMail aliases from Bitwarden app or browser extension? Easy.
1) In Bitwarden options for username generation select “Forwarded email alias”;
2) Select as service “Addy"
3) Enter as domain hidemail.app (in future you can add cu...]]></description><link>https://blog.daneke.ge/hidemailapp-bitwarden</link><guid isPermaLink="true">https://blog.daneke.ge/hidemailapp-bitwarden</guid><category><![CDATA[hidemail]]></category><category><![CDATA[email security]]></category><category><![CDATA[email]]></category><category><![CDATA[aliases]]></category><category><![CDATA[privacy]]></category><dc:creator><![CDATA[George Daneke]]></dc:creator><pubDate>Thu, 29 May 2025 17:00:09 GMT</pubDate><content:encoded><![CDATA[<p>You want to generate HideMail aliases from Bitwarden app or browser extension? Easy.</p>
<p>1) In Bitwarden options for username generation select “Forwarded email alias”;</p>
<p>2) Select as service “Addy"</p>
<p>3) Enter as domain hidemail.app (in future you can add custom domains! and even have one as catch-all domain with auto-created alias. Want to try? Write me to be invited to beta test!)</p>
<p>4) Generate API key (here: <a target="_blank" href="https://hidemail.app/user/api-tokens">https://hidemail.app/user/api-tokens</a>) and paste it to “API Key”</p>
<p>5) For “Self-host server URL” write https://hidemail.app</p>
<p>6) Done! Now when you click generate username it will generate alias from hidemail.app!</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1748526956223/20a50a93-5e6f-4c3a-aa1f-a52fdd88fff7.png" alt class="image--center mx-auto" /></p>
]]></content:encoded></item><item><title><![CDATA[Fixing Google Sign-In Errors: A Step-by-Step Guide for Android Developers]]></title><description><![CDATA[So you released your first application on Google Play with Google Sign-In and now you're facing this error:
Error: Google Sign-In failed: [16] Account reauth failed.
Something like that:

You already tried
keytool -printcert -jarfile ./android/app/re...]]></description><link>https://blog.daneke.ge/fixing-google-sign-in-errors-a-step-by-step-guide-for-android-developers</link><guid isPermaLink="true">https://blog.daneke.ge/fixing-google-sign-in-errors-a-step-by-step-guide-for-android-developers</guid><category><![CDATA[android app development]]></category><category><![CDATA[google sign in]]></category><category><![CDATA[oauth]]></category><dc:creator><![CDATA[George Daneke]]></dc:creator><pubDate>Sun, 23 Mar 2025 08:37:44 GMT</pubDate><content:encoded><![CDATA[<p>So you released your first application on Google Play with Google Sign-In and now you're facing this error:</p>
<h3 id="heading-error-google-sign-in-failed-16-account-reauth-failed"><mark>Error: Google Sign-In failed: [16] Account reauth failed.</mark></h3>
<p>Something like that:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1742718321336/4aaf3a79-ff61-4e17-9aa2-800e3889be48.png" alt class="image--center mx-auto" /></p>
<p>You already tried</p>
<pre><code class="lang-plaintext">keytool -printcert -jarfile ./android/app/release/app-release.aab
</code></pre>
<p>or</p>
<pre><code class="lang-plaintext">keytool -keystore "path to your keystore file" -list -v
</code></pre>
<p>…but it’s still not working. I know what to do! All of this because you enabled <strong>App signing on Google Play Console</strong> and have to use SHA-1 certificate fingerprint from the <strong>App signing key certificate</strong> there.</p>
<p>Go to Google Play Console → select your app → Test and release → Setup → App signing → find <strong>App signing key certificate and copy</strong> SHA-1 certificate fingerprint. Copy it.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1742718563780/660f7eae-6110-4a42-b079-fff5b74b521a.png" alt class="image--center mx-auto" /></p>
<p>Now open your project on Google Console → Google Auth Platform → Clients → Create client → type Android → write your package name from gradle file → paste your SHA-1 certificate fingerprint there</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1742718655878/1299c047-f7e0-46ac-ba03-9902fc55a416.png" alt class="image--center mx-auto" /></p>
<p>Done! Now it’s working.</p>
]]></content:encoded></item><item><title><![CDATA[How to Add Hetzner S3 Object Storage to Laravel 12 App]]></title><description><![CDATA[Hetzner's S3-compatible Object Storage provides a scalable and cost-effective solution for storing and retrieving large amounts of data. In this guide, we'll walk through the process of integrating Hetzner S3 Object Storage with a Laravel 11 applicat...]]></description><link>https://blog.daneke.ge/how-to-add-hetzner-s3-object-storage-to-laravel-12-app</link><guid isPermaLink="true">https://blog.daneke.ge/how-to-add-hetzner-s3-object-storage-to-laravel-12-app</guid><category><![CDATA[Hetzner]]></category><category><![CDATA[Laravel]]></category><category><![CDATA[object storage]]></category><category><![CDATA[S3-bucket]]></category><category><![CDATA[AWS]]></category><dc:creator><![CDATA[George Daneke]]></dc:creator><pubDate>Fri, 18 Oct 2024 13:19:48 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1729257528169/880e489c-f48b-4bdc-866c-1914a9334f2d.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Hetzner's S3-compatible Object Storage provides a scalable and cost-effective solution for storing and retrieving large amounts of data. In this guide, we'll walk through the process of integrating Hetzner S3 Object Storage with a Laravel 11 application.</p>
<h2 id="heading-prerequisites">Prerequisites</h2>
<ul>
<li><p>A Laravel 12 application</p>
</li>
<li><p>A Hetzner Cloud account with Object Storage enabled</p>
</li>
<li><p>Composer installed on your development machine</p>
</li>
</ul>
<h2 id="heading-step-1-install-the-aws-sdk-for-php">Step 1: Install the AWS SDK for PHP</h2>
<p>Laravel uses the AWS SDK for PHP to interact with S3-compatible storage services. Install it using Composer:</p>
<pre><code class="lang-bash">composer require league/flysystem-aws-s3-v3 <span class="hljs-string">"^3.0"</span> --with-all-dependencies
</code></pre>
<h2 id="heading-step-2-create-hetzner-s3-bucket-and-generate-credentials">Step 2: Create Hetzner S3 bucket and generate credentials</h2>
<p>Create new bucket via interface on hetzner.com and remember your bucket name:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1742719786579/34f46a04-c7e9-435b-978e-48585219caba.png" alt class="image--center mx-auto" /></p>
<p>Than generate your credentials:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1729256829788/0a9024ac-aff8-4232-9aa1-84381f6c001d.png" alt class="image--center mx-auto" /></p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1729256858272/807f6c86-91b3-401a-a56a-1d93c0dab19b.png" alt class="image--center mx-auto" /></p>
<h2 id="heading-step-3-configure-hetzner-s3-credentials">Step 3: Configure Hetzner S3 Credentials</h2>
<p>Add your Hetzner S3 credentials to your Laravel application's <code>.env</code> file:</p>
<pre><code class="lang-plaintext">HETZNER_S3_ACCESS_KEY_ID=your_access_key
HETZNER_S3_SECRET_ACCESS_KEY=your_secret_key
HETZNER_S3_BUCKET=your_bucket_name
HETZNER_S3_ENDPOINT=https://fsn1.your-objectstorage.com
</code></pre>
<p>Replace <code>your_access_key</code>, <code>your_secret_key</code>, and <code>your_bucket_name</code> with your actual Hetzner S3 credentials and bucket name.</p>
<h2 id="heading-step-4-update-filesystem-configuration">Step 4: Update Filesystem Configuration</h2>
<p>Open <code>config/filesystems.php</code> and add a new disk configuration for Hetzner S3:</p>
<pre><code class="lang-php"><span class="hljs-string">'hetzner'</span> =&gt; [
    <span class="hljs-string">'driver'</span> =&gt; <span class="hljs-string">'s3'</span>,
    <span class="hljs-string">'key'</span> =&gt; env(<span class="hljs-string">'HETZNER_S3_ACCESS_KEY_ID'</span>),
    <span class="hljs-string">'secret'</span> =&gt; env(<span class="hljs-string">'HETZNER_S3_SECRET_ACCESS_KEY'</span>),
    <span class="hljs-string">'region'</span> =&gt; <span class="hljs-string">'us-east-1'</span>,
    <span class="hljs-string">'bucket'</span> =&gt; env(<span class="hljs-string">'HETZNER_S3_BUCKET'</span>),
    <span class="hljs-string">'endpoint'</span> =&gt; env(<span class="hljs-string">'HETZNER_S3_ENDPOINT'</span>),
    <span class="hljs-string">'use_path_style_endpoint'</span> =&gt; <span class="hljs-literal">true</span>,
    <span class="hljs-string">'throw'</span> =&gt; <span class="hljs-literal">false</span>,
    <span class="hljs-string">'visibility'</span> =&gt; <span class="hljs-string">'private'</span>,
],
</code></pre>
<h2 id="heading-step-5-use-hetzner-s3-in-your-application">Step 5: Use Hetzner S3 in Your Application</h2>
<p>Now you can use Laravel's Storage facade to interact with your Hetzner S3 bucket. Here are some examples:</p>
<h3 id="heading-uploading-a-file">Uploading a File</h3>
<pre><code class="lang-php"><span class="hljs-keyword">use</span> <span class="hljs-title">Illuminate</span>\<span class="hljs-title">Support</span>\<span class="hljs-title">Facades</span>\<span class="hljs-title">Storage</span>;

$file = $request-&gt;file(<span class="hljs-string">'avatar'</span>);
$path = Storage::disk(<span class="hljs-string">'hetzner'</span>)-&gt;put(<span class="hljs-string">'avatars'</span>, $file);
</code></pre>
<h3 id="heading-retrieving-a-file">Retrieving a File</h3>
<pre><code class="lang-php"><span class="hljs-keyword">use</span> <span class="hljs-title">Illuminate</span>\<span class="hljs-title">Support</span>\<span class="hljs-title">Facades</span>\<span class="hljs-title">Storage</span>;

$url = Storage::disk(<span class="hljs-string">'hetzner'</span>)-&gt;url(<span class="hljs-string">'avatars/filename.jpg'</span>);
</code></pre>
<h3 id="heading-deleting-a-file">Deleting a File</h3>
<pre><code class="lang-php"><span class="hljs-keyword">use</span> <span class="hljs-title">Illuminate</span>\<span class="hljs-title">Support</span>\<span class="hljs-title">Facades</span>\<span class="hljs-title">Storage</span>;

Storage::disk(<span class="hljs-string">'hetzner'</span>)-&gt;delete(<span class="hljs-string">'avatars/filename.jpg'</span>);
</code></pre>
<h2 id="heading-step-6-handle-file-urls">Step 6: Handle File URLs</h2>
<p>If you have private bucket (you should) - you can generate URLs of file when needed with <em>temporaryUrl</em></p>
<pre><code class="lang-php"><span class="hljs-keyword">use</span> <span class="hljs-title">Illuminate</span>\<span class="hljs-title">Support</span>\<span class="hljs-title">Facades</span>\<span class="hljs-title">Storage</span>;

Storage::disk(<span class="hljs-string">'hetzner'</span>)-&gt;temporaryUrl(<span class="hljs-string">'avatars/filename.jpg'</span>, now()-&gt;addMinutes(<span class="hljs-number">5</span>));
</code></pre>
<h2 id="heading-price">Price</h2>
<p>Hetzner's Object Storage pricing structure is designed to be both flexible and cost-effective. The service operates on a base price of €0.0081 per hour for Object Storage runtime, with a monthly cap of €4.99 for all Buckets under a project owner's account. This base price includes a generous allocation of 1 TB of storage (up to 744 TB-hours) and 1 TB of traffic across all Buckets in your account. Should you exceed these included quotas, additional storage is billed at €0.0067 per TB-hour, while extra traffic incurs a cost of €1.00 per TB. It's worth noting that all prices quoted exclude VAT, providing transparency in the cost structure. This pricing model allows users to start small and scale as needed, with the monthly cap offering predictability for budgeting purposes.</p>
<h2 id="heading-conclusion">Conclusion</h2>
<p>You've successfully integrated Hetzner S3 Object Storage with your Laravel 12 application. This setup allows you to leverage Hetzner's robust and scalable storage solution while using Laravel's familiar Storage facade. Remember to handle your S3 credentials securely and consider using Laravel's built-in configuration caching for production environments.</p>
<p>For more advanced usage, refer to Laravel's official documentation on file storage and the AWS SDK for PHP documentation.</p>
<p>Hetzner Docs are available here: <a target="_blank" href="https://docs.hetzner.com/storage/object-storage/">https://docs.hetzner.com/storage/object-storage/</a></p>
<p>Welcome to register on Hetzner with my referrer link: <a target="_blank" href="https://hetzner.cloud/?ref=jjQEPZtflL9T">https://hetzner.cloud/?ref=jjQEPZtflL9T</a></p>
]]></content:encoded></item><item><title><![CDATA[Social Login Management with Bitwarden]]></title><description><![CDATA[Or how to remember what social login I used on websites for "sign in"
Managing social logins efficiently is crucial in today's digital world. But you can simplify this process using Bitwarden or any other password manager like 1password.

Create a de...]]></description><link>https://blog.daneke.ge/social-login-management-with-bitwarden</link><guid isPermaLink="true">https://blog.daneke.ge/social-login-management-with-bitwarden</guid><category><![CDATA[privacy]]></category><category><![CDATA[social login]]></category><category><![CDATA[Bitwarden]]></category><category><![CDATA[tips]]></category><category><![CDATA[tips and tricks]]></category><dc:creator><![CDATA[George Daneke]]></dc:creator><pubDate>Fri, 29 Sep 2023 12:59:45 GMT</pubDate><content:encoded><![CDATA[<h2 id="heading-or-how-to-remember-what-social-login-i-used-on-websites-for-sign-in">Or how to remember what social login I used on websites for "sign in"</h2>
<p>Managing social logins efficiently is crucial in today's digital world. But you can simplify this process using Bitwarden or any other password manager like 1password.</p>
<ul>
<li><p>Create a dedicated login item for each website with your chosen social login method (e.g., "Login with Google" or "Login with Facebook").</p>
</li>
<li><p>Use custom fields to store extra details, like associated email addresses.</p>
</li>
</ul>
<p>Thats it! Try Bitwadren today: <a target="_blank" href="https://bitwarden.com/">https://bitwarden.com/</a> Best part - it is free to use!</p>
<p>Another tip: to protect your privacy, increase the security of your main email account, and prevent spam or any unwanted email you can also generate an email <strong>alias</strong> with an app I built for myself: <a target="_blank" href="http://HideMail.app">HideMail.app</a> (available for <a target="_blank" href="https://chrome.google.com/webstore/detail/hidemail-privacy-email-fo/mddolicabhpkinbdmdgbeajjcpckinhe">Chrome</a>, <a target="_blank" href="https://addons.mozilla.org/en-US/firefox/addon/hidemail-app/">Firefox</a>, <a target="_blank" href="https://microsoftedge.microsoft.com/addons/detail/nppehnganjfjokfdmkgohagglignoiek">Edge</a>, <a target="_blank" href="https://www.raycast.com/Flatroy/hide-mail">Raycast</a>, <a target="_blank" href="https://play.google.com/store/apps/details?id=com.hidemail.app&amp;utm_source=site&amp;pcampaignid=pcampaignidMKT-Other-global-all-co-prtnr-py-PartBadge-Mar2515-1">Google Android</a>, and <a target="_blank" href="https://www.icloud.com/shortcuts/5e6cff1d45e944b589aa734750f05fd8">Apple Shortcut</a>). In case of email leaks, you have the option to switch to a new email alias and deactivate forwarding for the previous one.</p>
]]></content:encoded></item><item><title><![CDATA[Pension insurance for a self-employed person (Israel)]]></title><description><![CDATA[This is a translation and a shorter version of the original Hebrew article with some additional information for myself.

A self-employed person (osek murshe or osek patur) must independently deposit sums of money for pension savings, at the rates det...]]></description><link>https://blog.daneke.ge/pension-insurance-for-a-self-employed-person-israel</link><guid isPermaLink="true">https://blog.daneke.ge/pension-insurance-for-a-self-employed-person-israel</guid><category><![CDATA[taxes]]></category><category><![CDATA[israel]]></category><category><![CDATA[Pension Fund]]></category><category><![CDATA[osek ]]></category><dc:creator><![CDATA[George Daneke]]></dc:creator><pubDate>Sat, 23 Sep 2023 16:27:47 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1695486536926/22a5864e-e6b7-4a1b-bdbf-ca97bf5665e1.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<details><summary></summary><div data-type="detailsContent">This is a translation and a shorter version of the original Hebrew <a target="_blank" href="https://www.kolzchut.org.il/he/%D7%91%D7%99%D7%98%D7%95%D7%97_%D7%A4%D7%A0%D7%A1%D7%99%D7%95%D7%A0%D7%99_%D7%9C%D7%A2%D7%95%D7%91%D7%93_%D7%A2%D7%A6%D7%9E%D7%90%D7%99">article</a> with some additional information for myself.</div></details>

<p>A <a target="_blank" href="https://www.kolzchut.org.il/he/%D7%A2%D7%95%D7%91%D7%93%D7%99%D7%9D_%D7%A2%D7%A6%D7%9E%D7%90%D7%99%D7%9D">self-employed person</a> <em>(osek murshe or osek patur)</em> must independently deposit sums of money for <a target="_blank" href="https://www.kolzchut.org.il/he/%D7%97%D7%99%D7%A1%D7%9B%D7%95%D7%9F_%D7%A4%D7%A0%D7%A1%D7%99%D7%95%D7%A0%D7%99">pension savings</a>, at the rates detailed in this article, until the end of the tax year</p>
<p>A self-employed worker is entitled to <a target="_blank" href="https://www.kolzchut.org.il/he/%D7%94%D7%98%D7%91%D7%95%D7%AA_%D7%91%D7%9E%D7%A1_%D7%94%D7%9B%D7%A0%D7%A1%D7%94_%D7%91%D7%92%D7%99%D7%9F_%D7%94%D7%A4%D7%A7%D7%93%D7%95%D7%AA_%D7%A2%D7%A6%D7%9E%D7%90%D7%99%D7%95%D7%AA_%D7%9C%D7%91%D7%99%D7%98%D7%95%D7%97_%D7%A4%D7%A0%D7%A1%D7%99%D7%95%D7%A0%D7%99">tax benefits</a> for self-employed deposits for pension insurance</p>
<p>A self-employed person may deposit additional amounts for pension insurance beyond the amounts set by law, thus increasing his pension savings and <a target="_blank" href="https://www.kolzchut.org.il/he/%D7%A7%D7%A6%D7%91%D7%AA_%D7%A4%D7%A0%D7%A1%D7%99%D7%94_%D7%97%D7%95%D7%93%D7%A9%D7%99%D7%AA">pension allowance as well as benefiting from additional tax benefits</a></p>
<h2 id="heading-the-minimum-deposit-rate-for-pension-insurance"><strong>The minimum deposit rate for pension insurance</strong></h2>
<ul>
<li><p>For a part of the income that is up to half of <a target="_blank" href="https://www.kolzchut.org.il/he/%D7%94%D7%A9%D7%9B%D7%A8_%D7%94%D7%9E%D7%9E%D7%95%D7%A6%D7%A2">the average salary</a> in the economy (i.e. for the first NIS 71,220 in the tax year) 4.45% of the income must be deposited.</p>
</li>
<li><p>For the rest of the income up to the average salary in the economy (i.e. up to NIS 142,440 per year) - 12.55% must be deposited.</p>
</li>
<li><p>For the part of the income above the average salary (i.e. for every shekel above NIS 142,440 per year) - there is no obligation to deposit for pension insurance. Self-employed persons who wish to increase their pension savings may set aside this part of their salary for pension insurance as well.</p>
</li>
<li><p>These rates will be calculated from the self-employed person's income after deducting from it the <a target="_blank" href="https://www.kolzchut.org.il/he/%D7%94%D7%95%D7%A6%D7%90%D7%94_%D7%9E%D7%95%D7%9B%D7%A8%D7%AA_%D7%9C%D7%A6%D7%95%D7%A8%D7%9A_%D7%97%D7%99%D7%A9%D7%95%D7%91_%D7%9E%D7%A1_%D7%94%D7%9B%D7%A0%D7%A1%D7%94_(%D7%94%D7%95%D7%A6%D7%90%D7%94_%D7%9E%D7%95%D7%AA%D7%A8%D7%AA_%D7%91%D7%A0%D7%99%D7%9B%D7%95%D7%99)">deductions permitted</a> by law, and before deducting from it the deductions due to a deposit to a training fund, pension insurance or another provident fund for annuity.</p>
</li>
</ul>
<h3 id="heading-examples-of-the-amount-of-deposits-for-pension-insurance"><strong>Examples of the amount of deposits for pension insurance</strong></h3>
<ul>
<li>A self-employed person whose annual income is NIS 96,000 (an average of NIS 8,000 per month) (after deductions for <a target="_blank" href="https://www.kolzchut.org.il/he/%D7%94%D7%95%D7%A6%D7%90%D7%94_%D7%9E%D7%95%D7%9B%D7%A8%D7%AA_%D7%9C%D7%A6%D7%95%D7%A8%D7%9A_%D7%97%D7%99%D7%A9%D7%95%D7%91_%D7%9E%D7%A1_%D7%94%D7%9B%D7%A0%D7%A1%D7%94_(%D7%94%D7%95%D7%A6%D7%90%D7%94_%D7%9E%D7%95%D7%AA%D7%A8%D7%AA_%D7%91%D7%A0%D7%99%D7%9B%D7%95%D7%99)">recognized expenses</a> and before deductions for contributions to provident funds and education funds):</li>
</ul>
<div class="hn-table">
<table>
<thead>
<tr>
<td><strong>Up to the amount of income (annual)</strong></td><td><strong>The deposit rate</strong></td><td><strong>The annual deposit amount</strong></td></tr>
</thead>
<tbody>
<tr>
<td>From 1 NIS to 71,220 NIS</td><td>4.45%</td><td>NIS 3,169.29</td></tr>
<tr>
<td>From NIS 71,221 to NIS 96,000</td><td>12.55%</td><td>NIS 3,109.89</td></tr>
<tr>
<td><strong>Total deposits per year</strong></td><td></td><td><strong>NIS 6,279.18</strong></td></tr>
</tbody>
</table>
</div><ul>
<li>A self-employed person whose annual income is NIS 180,000 (an average of NIS 15,000 per month) (after deductions for <a target="_blank" href="https://www.kolzchut.org.il/he/%D7%94%D7%95%D7%A6%D7%90%D7%94_%D7%9E%D7%95%D7%9B%D7%A8%D7%AA_%D7%9C%D7%A6%D7%95%D7%A8%D7%9A_%D7%97%D7%99%D7%A9%D7%95%D7%91_%D7%9E%D7%A1_%D7%94%D7%9B%D7%A0%D7%A1%D7%94_(%D7%94%D7%95%D7%A6%D7%90%D7%94_%D7%9E%D7%95%D7%AA%D7%A8%D7%AA_%D7%91%D7%A0%D7%99%D7%9B%D7%95%D7%99)">recognized expenses</a> and before deductions for contributions to provident funds and education funds):</li>
</ul>
<div class="hn-table">
<table>
<thead>
<tr>
<td><strong>Up to the amount of income (annual)</strong></td><td><strong>The deposit rate</strong></td><td><strong>The annual deposit amount</strong></td></tr>
</thead>
<tbody>
<tr>
<td>From 1 NIS to 71,220 NIS</td><td>4.45%</td><td>NIS 3,169.29</td></tr>
<tr>
<td>From NIS 71,221 to NIS 142,440</td><td>12.55%</td><td>NIS 8,938.11</td></tr>
<tr>
<td>For every shekel over NIS 142,441</td><td>No deposit required</td><td>0 NIS</td></tr>
<tr>
<td><strong>Total deposits per year</strong></td><td></td><td><strong>NIS 12,107.4</strong></td></tr>
</tbody>
</table>
</div><ul>
<li>A self-employed person whose annual income is NIS 180,000 (an average of NIS 15,000 per month) (after deductions for <a target="_blank" href="https://www.kolzchut.org.il/he/%D7%94%D7%95%D7%A6%D7%90%D7%94_%D7%9E%D7%95%D7%9B%D7%A8%D7%AA_%D7%9C%D7%A6%D7%95%D7%A8%D7%9A_%D7%97%D7%99%D7%A9%D7%95%D7%91_%D7%9E%D7%A1_%D7%94%D7%9B%D7%A0%D7%A1%D7%94_(%D7%94%D7%95%D7%A6%D7%90%D7%94_%D7%9E%D7%95%D7%AA%D7%A8%D7%AA_%D7%91%D7%A0%D7%99%D7%9B%D7%95%D7%99)">recognized expenses</a> and before deductions for contributions to provident funds and education funds) and who wants to receive maximum tax benefits for deposits (of a maximum of 16.5% of income up to the ceiling set by law)</li>
</ul>
<div class="hn-table">
<table>
<thead>
<tr>
<td><strong>Up to the amount of income (annual)</strong></td><td><strong>The deposit rate</strong></td><td><strong>The annual deposit amount</strong></td></tr>
</thead>
<tbody>
<tr>
<td>From 1 NIS to NIS 142,440</td><td>16.5%</td><td>NIS 23,502.6</td></tr>
<tr>
<td>For every shekel over NIS 142,441</td><td>No deposit required</td><td>0 NIS</td></tr>
<tr>
<td><strong>Total deposits per year</strong></td><td></td><td><strong>NIS 23,502.6</strong></td></tr>
</tbody>
</table>
</div><h3 id="heading-self-employed-who-is-also-an-employee-at-the-same-time"><strong>Self-employed who is also an employee at the same time</strong></h3>
<ul>
<li>A self-employed person who is employed at the same time as an employee at a certain workplace must contribute to the pension insurance himself, only if the amount set aside for him as an employee (the employer's contributions and the employee's contributions) is lower than the amount he must set aside as a self-employed person for his income from the business, and up to this amount.</li>
</ul>
<p><strong>Example</strong></p>
<p>If the income of a self-employed person from the business requires a provision of NIS 5,000 for the pension insurance, and as part of his work as an employee the employer's contributions and the employee's contributions amount to NIS 4,000, he must deposit another NIS 1,000 as a self-employed person. If, as part of his work as an employee, the contributions of the employee and the employer exceed NIS 5,000, he is not required to deposit any amount for the pension insurance as a self-employed person.</p>
<h2 id="heading-target-population-and-prerequisites"><strong>Target population and prerequisites</strong></h2>
<ul>
<li><p><a target="_blank" href="https://www.kolzchut.org.il/he/%D7%A2%D7%95%D7%91%D7%93%D7%99%D7%9D_%D7%A2%D7%A6%D7%9E%D7%90%D7%99%D7%9D">An independent worker</a> who meets the following two conditions:</p>
<ol>
<li><p>He is between the ages of 21-60.</p>
</li>
<li><p>He is <a target="_blank" href="https://www.kolzchut.org.il/he/%D7%A4%D7%AA%D7%99%D7%97%D7%AA_%D7%AA%D7%99%D7%A7_%D7%A2%D7%95%D7%A1%D7%A7_%D7%91%D7%9E%D7%A1_%D7%A2%D7%A8%D7%9A_%D7%9E%D7%95%D7%A1%D7%A3_(%D7%9E%D7%A2%22%D7%9E)">registered as a value-added tax practitioner</a> for at least 6 months.</p>
</li>
</ol>
</li>
<li><p>Despite this, a self-employed worker whose age on 01.01.2017 was 55 years or older is exempt from pension savings deposits.</p>
</li>
</ul>
<h2 id="heading-the-steps-of-the-procedure"><strong>The steps of the procedure</strong></h2>
<ul>
<li><p>You must contact one of <a target="_blank" href="https://www.kolzchut.org.il/he/%D7%92%D7%95%D7%A3_%D7%9E%D7%95%D7%A1%D7%93%D7%99_(%D7%92%D7%95%D7%A3_%D7%A4%D7%A0%D7%A1%D7%99%D7%95%D7%A0%D7%99)">the pension entities</a> (pension funds, insurance companies or provident funds) where you can manage your pension savings, to open a savings account.</p>
</li>
<li><p>You must choose the type of pension insurance ( <a target="_blank" href="https://www.kolzchut.org.il/he/%D7%A7%D7%A8%D7%9F_%D7%A4%D7%A0%D7%A1%D7%99%D7%94">pension</a> fund, <a target="_blank" href="https://www.kolzchut.org.il/he/%D7%91%D7%99%D7%98%D7%95%D7%97_%D7%9E%D7%A0%D7%94%D7%9C%D7%99%D7%9D">executive insurance</a> or <a target="_blank" href="https://www.kolzchut.org.il/he/%D7%A7%D7%95%D7%A4%D7%AA_%D7%92%D7%9E%D7%9C">provident fund</a> ) as well as the <a target="_blank" href="https://www.kolzchut.org.il/he/%D7%91%D7%97%D7%99%D7%A8%D7%AA_%D7%9E%D7%A1%D7%9C%D7%95%D7%9C_%D7%94%D7%94%D7%A9%D7%A7%D7%A2%D7%94_%D7%A9%D7%9C_%D7%9B%D7%A1%D7%A4%D7%99_%D7%94%D7%91%D7%99%D7%98%D7%95%D7%97_%D7%94%D7%A4%D7%A0%D7%A1%D7%99%D7%95%D7%A0%D7%99">savings route</a> in which the funds will be invested.</p>
</li>
<li><p>Several forms must be filled out, which mainly include the insured's personal details as well as a letter of authorization to deduct the funds from the bank account.</p>
</li>
<li><p>The insured may be required to provide medical information about his condition and even provide the pension body with medical documents ( <a target="_blank" href="https://www.kolzchut.org.il/he/%D7%97%D7%99%D7%AA%D7%95%D7%9D">underwriting procedure</a> ).</p>
</li>
<li><p>The deposits can be made at any time during the year. You can make multiple deposits or a one-time deposit. (Since in many cases self-employed workers can only verify the amount of their annual income near the end of the tax year, they may prefer to make a one-time deposit at the end of the year, then they will be able to know the amount of the required deposit).</p>
</li>
<li><p>The contributions to the pension insurance must be made by the end of the tax year in which the payments are made.</p>
</li>
<li><p>For information on the deposit procedure and the method of deposits, see <a target="_blank" href="https://www.kolzchut.org.il/he/%D7%94%D7%A4%D7%A7%D7%93%D7%95%D7%AA_%D7%A2%D7%A6%D7%9E%D7%90%D7%99%D7%95%D7%AA_%D7%9C%D7%91%D7%99%D7%98%D7%95%D7%97_%D7%A4%D7%A0%D7%A1%D7%99%D7%95%D7%A0%D7%99">independent deposits for pension insurance</a>.</p>
</li>
</ul>
<h2 id="heading-violation-of-the-obligation-to-deposit-funds-for-pension-insurance"><strong>Violation of the obligation to deposit funds for pension insurance</strong></h2>
<ul>
<li><p>Beginning with the 2018 tax year, fines can be imposed on self-employed individuals whose income exceeds NIS 66,861 per year (as of 2023) and who have not deposited the amounts and rates stipulated by law into the pension insurance.</p>
</li>
<li><p>Before imposing the fine, the centre for the collection of fines will send a notice to those self-employed included in the list, according to which if they do not deposit within 90 days the legally deficient contributions to the pension insurance, they will be fined.</p>
</li>
<li><p>A fine of 500 NIS will be imposed on self-employed persons who received a warning and nevertheless did not deposit the amounts required for the pension insurance (the amount will be updated annually according to the index change rate).</p>
</li>
<li><p>The fines will be imposed as of December 1, 2019, due to the 2018 tax year.</p>
</li>
</ul>
<h2 id="heading-tax-benefits-for-the-self-employed-who-deposited-funds-for-pension-insurance"><strong>Tax benefits for the self-employed who deposited funds for pension insurance</strong></h2>
<ul>
<li><p>A self-employed person is entitled to tax benefits on pension insurance deposits.</p>
</li>
<li><p>Tax benefits are also given for deposits in amounts and rates higher than the minimum deposit rates listed above.</p>
</li>
<li><p><strong>You can receive tax benefits for deposits of a maximum of 16.5% of income up to the ceiling set by law.</strong></p>
</li>
<li><p>The benefits will be given only for the year in which the funds were actually deposited for the pension insurance. That is why it is important to make sure that the funds reach the <a target="_blank" href="https://www.kolzchut.org.il/he/%D7%92%D7%95%D7%A3_%D7%9E%D7%95%D7%A1%D7%93%D7%99_(%D7%92%D7%95%D7%A3_%D7%A4%D7%A0%D7%A1%D7%99%D7%95%D7%A0%D7%99)">pension body</a> where the pension savings are conducted before the end of December.</p>
</li>
<li><p>For more information, see <a target="_blank" href="https://www.kolzchut.org.il/he/%D7%94%D7%98%D7%91%D7%95%D7%AA_%D7%91%D7%9E%D7%A1_%D7%94%D7%9B%D7%A0%D7%A1%D7%94_%D7%91%D7%92%D7%99%D7%9F_%D7%94%D7%A4%D7%A7%D7%93%D7%95%D7%AA_%D7%A2%D7%A6%D7%9E%D7%90%D7%99%D7%95%D7%AA_%D7%9C%D7%91%D7%99%D7%98%D7%95%D7%97_%D7%A4%D7%A0%D7%A1%D7%99%D7%95%D7%A0%D7%99">income tax benefits for independent deposits for pension</a> insurance.</p>
</li>
</ul>
<p><strong>pay attention</strong></p>
<p><strong>The deposit for pension insurance does not affect eligibility for a work grant</strong></p>
<ul>
<li><p>The deposit does not reduce the amount of income for eligibility for the grant.</p>
<ul>
<li><p>Those whose income before the pension insurance deposit was too high and therefore were not entitled to the grant, will not be able to benefit from the grant by making a pension insurance deposit.</p>
</li>
<li><p>For more information, see <a target="_blank" href="https://www.kolzchut.org.il/he/%D7%9E%D7%A2%D7%A0%D7%A7_%D7%A2%D7%91%D7%95%D7%93%D7%94_(%D7%9E%D7%A2%D7%A0%D7%A7_%D7%94%D7%9B%D7%A0%D7%A1%D7%94,_%D7%9E%D7%A1_%D7%94%D7%9B%D7%A0%D7%A1%D7%94_%D7%A9%D7%9C%D7%99%D7%9C%D7%99)#.D7.94.D7.94.D7.9B.D7.A0.D7.A1.D7.95.D7.AA_.D7.A9.D7.9E.D7.A9.D7.A4.D7.99.D7.A2.D7.95.D7.AA_.D7.A2.D7.9C_.D7.94.D7.96.D7.9B.D7.90.D7.95.D7.AA_.D7.9C.D7.9E.D7.A2.D7.A0.D7.A7">Work grant (income grant, negative income tax)</a> (in the paragraph "Incomes that affect eligibility for the grant").</p>
</li>
</ul>
</li>
</ul>
<h2 id="heading-the-reduction-of-payments-to-the-national-insurance-due-to-independent-deposits-for-the-pension-insurance"><strong>The reduction of payments to the National Insurance due to independent deposits for the pension insurance</strong></h2>
<ul>
<li><p>Independent deposits for pension insurance may reduce the amount of "taxable income" for payments to the National Insurance Institute.</p>
</li>
<li><p>A self-employed person who deposited sums for pension insurance <strong>and chose to receive a "deduction" benefit for them</strong> (up to the qualifying ceiling), will also benefit from a reduction in the amount of <a target="_blank" href="https://www.kolzchut.org.il/he/%D7%93%D7%9E%D7%99_%D7%91%D7%99%D7%98%D7%95%D7%97_%D7%9C%D7%90%D7%95%D7%9E%D7%99_%D7%9C%D7%A2%D7%A6%D7%9E%D7%90%D7%99">the National Insurance premiums</a> and health insurance premiums at a rate that can reach 17.83% of the amount deposited for the pension insurance and recognized for the income tax deduction benefit.</p>
</li>
<li><p>For more information, see <a target="_blank" href="https://www.kolzchut.org.il/he/%D7%94%D7%98%D7%91%D7%95%D7%AA_%D7%91%D7%9E%D7%A1_%D7%94%D7%9B%D7%A0%D7%A1%D7%94_%D7%91%D7%92%D7%99%D7%9F_%D7%94%D7%A4%D7%A7%D7%93%D7%95%D7%AA_%D7%A2%D7%A6%D7%9E%D7%90%D7%99%D7%95%D7%AA_%D7%9C%D7%91%D7%99%D7%98%D7%95%D7%97_%D7%A4%D7%A0%D7%A1%D7%99%D7%95%D7%A0%D7%99#.D7.94.D7.A9.D7.A4.D7.A2.D7.AA_.D7.94.D7.94.D7.A4.D7.A7.D7.93.D7.94_.D7.9C.D7.91.D7.99.D7.98.D7.95.D7.97_.D7.A4.D7.A0.D7.A1.D7.99.D7.95.D7.A0.D7.99_.D7.A2.D7.9C_.D7.94.D7.AA.D7.A9.D7.9C.D7.95.D7.9E.D7.99.D7.9D_.D7.9C.D7.91.D7.99.D7.98.D7.95.D7.97_.D7.9C.D7.90.D7.95.D7.9E.D7.99">income tax benefits for self-employed deposits for pension insurance</a> (in the paragraph "The effect of the deposit for pension insurance on the payments to the National Insurance").</p>
</li>
</ul>
<h2 id="heading-withdrawal-of-funds-in-unemployment-situations"><strong>Withdrawal of funds in unemployment situations</strong></h2>
<ul>
<li><p>During the year 2021, a self-employed person who deposited funds for pension savings by the law, could withdraw certain amounts from the pension savings, in any of the following situations:</p>
<ul>
<li><p>The independent closed the business.</p>
</li>
<li><p>The self-employed person has reached <a target="_blank" href="https://www.kolzchut.org.il/he/%D7%92%D7%99%D7%9C_%D7%A4%D7%A8%D7%99%D7%A9%D7%94_%D7%9E%D7%A2%D7%91%D7%95%D7%93%D7%94">retirement age</a> and has no income that is required to contribute to pension insurance.</p>
</li>
<li><p>The self-employed person stopped practicing his profession.</p>
</li>
<li><p>The self-employed person closed his business for <strong>a cumulative period of at least one month</strong> during the years 2020-2021 due to restrictions placed on opening businesses during <a target="_blank" href="https://www.kolzchut.org.il/he/%D7%A7%D7%95%D7%A8%D7%95%D7%A0%D7%94">the corona crisis</a> (according to <a target="_blank" href="https://www.nevo.co.il/law_html/law01/502_325.htm">the law on special powers to deal with the corona virus</a> ).</p>
</li>
</ul>
</li>
<li><p>For more information, see <a target="_blank" href="https://www.kolzchut.org.il/he/%D7%9E%D7%A9%D7%99%D7%9B%D7%AA_%D7%9B%D7%A1%D7%A4%D7%99%D7%9D_%D7%9E%D7%94%D7%91%D7%99%D7%98%D7%95%D7%97_%D7%94%D7%A4%D7%A0%D7%A1%D7%99%D7%95%D7%A0%D7%99_%D7%90%D7%95_%D7%9E%D7%A7%D7%95%D7%A4%D7%AA_%D7%92%D7%9E%D7%9C_%D7%9C%D7%A2%D7%A6%D7%9E%D7%90%D7%99_%D7%A9%D7%A1%D7%92%D7%A8_%D7%90%D7%AA_%D7%94%D7%A2%D7%A1%D7%A7_%D7%90%D7%95_%D7%94%D7%A4%D7%A1%D7%99%D7%A7_%D7%9C%D7%A2%D7%A1%D7%95%D7%A7_%D7%91%D7%9E%D7%A9%D7%9C%D7%97_%D7%99%D7%93%D7%95">withdrawing funds from the pension insurance or provident fund for a self-employed person who has closed his business or stopped practicing his profession</a> .</p>
</li>
</ul>
<h2 id="heading-important-information"><strong>Important Information</strong></h2>
<ul>
<li><p>A self-employed person may deposit additional amounts for pension insurance beyond the amounts stipulated by law, and thus increase his pension savings (and <a target="_blank" href="https://www.kolzchut.org.il/he/%D7%A7%D7%A6%D7%91%D7%AA_%D7%A4%D7%A0%D7%A1%D7%99%D7%94_%D7%97%D7%95%D7%93%D7%A9%D7%99%D7%AA">the pension allowance</a> ) and enjoy additional tax benefits.</p>
</li>
<li><p>It is important to find out the terms of the pension insurance, including the amount of <a target="_blank" href="https://www.kolzchut.org.il/he/%D7%93%D7%9E%D7%99_%D7%A0%D7%99%D7%94%D7%95%D7%9C_%D7%97%D7%A9%D7%91%D7%95%D7%9F_%D7%91%D7%99%D7%98%D7%95%D7%97_%D7%A4%D7%A0%D7%A1%D7%99%D7%95%D7%A0%D7%99">the management fees</a> that the pension body collects from the savers. In some cases, it is possible to negotiate the amount of the management fee.</p>
</li>
<li><p>It is important to choose the investment channel in which the funds that the saver deposits into the fund will be invested. For more information, see <a target="_blank" href="https://www.kolzchut.org.il/he/%D7%91%D7%97%D7%99%D7%A8%D7%AA_%D7%9E%D7%A1%D7%9C%D7%95%D7%9C_%D7%94%D7%94%D7%A9%D7%A7%D7%A2%D7%94_%D7%A9%D7%9C_%D7%9B%D7%A1%D7%A4%D7%99_%D7%94%D7%91%D7%99%D7%98%D7%95%D7%97_%D7%94%D7%A4%D7%A0%D7%A1%D7%99%D7%95%D7%A0%D7%99">the selection of the investment route of the pension insurance funds</a> .</p>
</li>
<li><p>In addition, a self-employed person may deposit payments to a training fund for the self-employed, and enjoy additional tax benefits. For more information, see <a target="_blank" href="https://www.kolzchut.org.il/he/%D7%A7%D7%A8%D7%9F_%D7%94%D7%A9%D7%AA%D7%9C%D7%9E%D7%95%D7%AA_%D7%9C%D7%A2%D7%95%D7%91%D7%93_%D7%A2%D7%A6%D7%9E%D7%90%D7%99">the Self-Employed Training Fund</a>.</p>
</li>
</ul>
<h2 id="heading-what-is-the-most-popular-pension-fund-in-israel">What is the most popular pension fund in Israel?</h2>
<p>Some popular pension funds in Israel include:</p>
<ul>
<li><p>Altshuler Shaham</p>
</li>
<li><p>Migdal Makefet</p>
</li>
<li><p>Meitav</p>
</li>
<li><p>Phoenix</p>
</li>
</ul>
<p>If you are in Altshuler Shaham, they will provide you with details on how to send money and after every transfer, you need to send an email to <a target="_blank" href="mailto:sherut@altshul.co.il">sherut@altshul.co.il</a> with this information:</p>
<ul>
<li><p>Screenshot of transfer from your bank</p>
</li>
<li><p>and email like this:</p>
<p>  ```plaintext
    היי!</p>
</li>
</ul>
<p>      אני, [NAME SURNAME]:</p>
<p>      תז: [ID]</p>
<p>      סכום: [SUM[ שקלים</p>
<p>      לשנת [YEAR] כולה, ב-[sum per month] שקלים לחודש</p>
<p>      תודה
    ```</p>
]]></content:encoded></item><item><title><![CDATA[Easily delete all objects from Cloudflare R2 Bucket]]></title><description><![CDATA[Does anyone know an easy way to delete all objects from R2 or any other S3 object storage? I have a few suggestions for now: Cyberduck or Rclone.
1) Cyberduck a free program where you can connect to your bucket as it is Amazon S3 storage:

Put your s...]]></description><link>https://blog.daneke.ge/easily-delete-all-objects-from-cloudflare-r2-bucket</link><guid isPermaLink="true">https://blog.daneke.ge/easily-delete-all-objects-from-cloudflare-r2-bucket</guid><category><![CDATA[Cloudflare-r2]]></category><category><![CDATA[S3-bucket]]></category><dc:creator><![CDATA[George Daneke]]></dc:creator><pubDate>Sun, 20 Aug 2023 14:10:06 GMT</pubDate><content:encoded><![CDATA[<p>Does anyone know an easy way to delete all objects from R2 or any other S3 object storage? I have a few suggestions for now: <a target="_blank" href="https://cyberduck.io/">Cyberduck</a> or Rclone.</p>
<p>1) Cyberduck a free program where you can connect to your bucket as it is Amazon S3 storage:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1692540502089/e9d511d3-7810-46f5-8911-e8599f7129ce.png" alt class="image--center mx-auto" /></p>
<p>Put your server URL, Access Key ID and put bucket name to Path and then you can delete folders, files, or everything at once - but it will take time.</p>
<p>2) Rclone</p>
<p>You can read about how to configure it on the Cloudflare web-site: <a target="_blank" href="https://developers.cloudflare.com/r2/examples/rclone/">https://developers.cloudflare.com/r2/examples/rclone/</a> and then you can do something like this: rclone purge s3:{{bucket_name}}</p>
]]></content:encoded></item><item><title><![CDATA[How to hide your email address on LinkedIn]]></title><description><![CDATA[I have a catch-all email address for my domain name email and I noted a lot of spam from LinkedIn for random usernames (like alex@mydomain.com - that do not even exist), and I have figured out they are leaking my email address! And my bad: I hadn't u...]]></description><link>https://blog.daneke.ge/how-to-hide-your-email-address-on-linkedin</link><guid isPermaLink="true">https://blog.daneke.ge/how-to-hide-your-email-address-on-linkedin</guid><category><![CDATA[LinkedIn]]></category><category><![CDATA[#Spam protection]]></category><dc:creator><![CDATA[George Daneke]]></dc:creator><pubDate>Wed, 16 Aug 2023 16:40:25 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1692203503108/31e93af3-fa60-45e2-9f6e-2fbd337dbdab.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>I have a catch-all email address for my domain name email and I noted a lot of spam from LinkedIn for random usernames (like alex@mydomain.com - that do not even exist), and I have figured out they are leaking my email address! And my bad: I hadn't used <a target="_blank" href="https://hidemail.app">HideMail.app</a> or Hide My Email service from Apple for it...</p>
<p>As I know now, LinkedIn has the option to control who can see your email address on your profile and in this small guide I will show you how.</p>
<p>To open this section, on the desktop version of their site click "<strong>Me</strong>":</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1692202977562/a05c02d7-cffa-43c0-81bf-6d788eed0be7.png" alt class="image--center mx-auto" /></p>
<p>Click "<strong>Settings &amp; Privacy</strong>":</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1692203047824/a2cfa48c-768d-443a-9401-d8666c017afb.png" alt class="image--center mx-auto" /></p>
<p>Click "<strong>Visibility</strong>":</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1692203153369/7a3467a0-f373-49ab-a7e8-0dc2f8400374.png" alt class="image--center mx-auto" /></p>
<p>And only now you can change your email visibility and hide it from robots and spammers:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1692202754877/27c0da70-0913-4265-9c50-4d3cda854ee2.png" alt class="image--center mx-auto" /></p>
<p>Click "<strong>Only visible to me</strong>" and you are done.</p>
<p>There is another option, that works for any website – you can also generate an email alias with my <a target="_blank" href="https://hidemail.app">HideMail.app</a> or its browser extension (<a target="_blank" href="https://chrome.google.com/webstore/detail/hidemail-privacy-email-fo/mddolicabhpkinbdmdgbeajjcpckinhe">Chrome</a>, <a target="_blank" href="https://addons.mozilla.org/en-US/firefox/addon/hidemail-app/">Firefox</a>). In case of email leaks leading to spam or unwanted messages, you have the option to switch to a new email alias and deactivate forwarding for the previous one.</p>
]]></content:encoded></item><item><title><![CDATA[Your Apple Push Services will expire in 30 days.]]></title><description><![CDATA[You got this email from Apple and you don't know what to do? Or you saw in the Apple Developer console in the Certificates, Identifiers & Profiles section that this certificate is expiring soon?
It means you need to renew your app Push Notification C...]]></description><link>https://blog.daneke.ge/your-apple-push-services-will-expire-in-30-days</link><guid isPermaLink="true">https://blog.daneke.ge/your-apple-push-services-will-expire-in-30-days</guid><category><![CDATA[Apple]]></category><category><![CDATA[guide]]></category><dc:creator><![CDATA[George Daneke]]></dc:creator><pubDate>Sun, 13 Aug 2023 22:34:14 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1691924844118/ec52de9f-720e-4bfa-9b43-b2a96067ac2a.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>You got this email from Apple and you don't know what to do? Or you saw in the Apple Developer console in the Certificates, Identifiers &amp; Profiles section that this certificate is expiring soon?</p>
<p>It means you need to renew your app Push Notification Certificate. Here are the steps:</p>
<ol>
<li><p>Login to Developers account -&gt; Certificates, IDs &amp; Profiles and verify the expiring certificate.</p>
</li>
<li><p>Go to Identifiers -&gt; App IDs -&gt; Click on the AppId -&gt; Scroll down to Push Notifications -&gt; Edit -&gt; Click "Create Certificate" under "Production SSL Certificate".</p>
</li>
<li><p>Create certificate signing request from Keychain Access on your Mac:</p>
<ol>
<li><p>Launch Keychain Access -&gt; Choose Keychain Access -&gt; Certificate Assistant -&gt; Request a Certificate from a Certificate Authority.</p>
</li>
<li><p>In the Certificate Assistant dialogue, enter an email address in the User Email Address field.</p>
</li>
<li><p>In the Common Name field, enter a name for the key</p>
</li>
<li><p>Leave the CA Email Address field empty.</p>
</li>
<li><p>Choose “Saved to disk”, click Continue and save it in the computer.</p>
</li>
</ol>
</li>
<li><p>Go back to the Apple developer site and upload the CSR created in the above step -&gt; Continue -&gt; Download the certificate on your Mac.</p>
</li>
<li><p>Double-click on the downloaded cert to install it in Keychain on your Mac.<br /> Open Keychain Access -&gt; Certificates -&gt; The new cert and its private key should be listed there.</p>
</li>
<li><p>Export the certificate for your push notification client: Right-click on the cert in the Keychain Access-&gt; select "Export Apple Push Certificate: " -&gt; leave the password empty -&gt; save as a P12 file.</p>
</li>
<li><p>Login to Firebase -&gt; Project settings -&gt; Cloud Messaging -&gt; APNs Certificates -&gt; Upload your P12 file (Could be you use any other third-party instead of Firebase, find out yourself)</p>
</li>
</ol>
]]></content:encoded></item><item><title><![CDATA[Outline VPN: How to Access Performance Metrics?]]></title><description><![CDATA[Note: looking for a free Outline VPN? Try my bot: https://t.me/hidemail_vpn_bot
First, you need to open the Prometheus dashboard.

Connect to your server and forward port 9090:

ssh ${YUOR_USERNAME}@${YOUR_SERVER} -L 9090:localhost:9090


Open https:...]]></description><link>https://blog.daneke.ge/outline-vpn-how-to-access-performance-metrics</link><guid isPermaLink="true">https://blog.daneke.ge/outline-vpn-how-to-access-performance-metrics</guid><category><![CDATA[outlinevpn]]></category><category><![CDATA[#prometheus]]></category><dc:creator><![CDATA[George Daneke]]></dc:creator><pubDate>Sun, 13 Aug 2023 10:58:22 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1691924267800/bc07acf6-21ba-4494-81ba-21b30486ba5f.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Note: looking for a free Outline VPN? Try my bot: <a target="_blank" href="https://t.me/hidemail_vpn_bot">https://t.me/hidemail_vpn_bot</a></p>
<p>First, you need to open the Prometheus dashboard.</p>
<ol>
<li>Connect to your server and forward port 9090:</li>
</ol>
<pre><code class="lang-bash">ssh <span class="hljs-variable">${YUOR_USERNAME}</span>@<span class="hljs-variable">${YOUR_SERVER}</span> -L 9090:localhost:9090
</code></pre>
<ol>
<li><p>Open <a target="_blank" href="https://localhost:9090/graph">https://localhost:9090/graph</a> on your browser</p>
</li>
<li><p>Write the <a target="_blank" href="https://prometheus.io/docs/prometheus/latest/querying/basics/">PromQL</a> query you need. See the examples below.</p>
</li>
</ol>
<h1 id="heading-example-queries">Example Queries</h1>
<h2 id="heading-usage">Usage</h2>
<h3 id="heading-data-bytes">Data Bytes</h3>
<p>By access key, protocol and direction</p>
<pre><code class="lang-php">increase(shadowsocks_data_bytes[<span class="hljs-number">1</span>d])
</code></pre>
<p>To aggregate by access key only:</p>
<pre><code class="lang-php">sum(increase(shadowsocks_data_bytes[<span class="hljs-number">1</span>d])) by (access_key)
</code></pre>
<p>This is the query used to calculate the usage for data limits (from <a target="_blank" href="https://github.com/Jigsaw-Code/outline-server/blob/1ac9f238132d5917b42d4b6615727e477aa7bbc0/src/shadowbox/server/manager_metrics.ts#L31">manager_metrics.ts</a>):</p>
<pre><code class="lang-php">sum(increase(shadowsocks_data_bytes{dir=~<span class="hljs-string">"c&lt;p|p&gt;t"</span>}[<span class="hljs-number">30</span>d])) by (access_key)
</code></pre>
<p>By location, protocol and direction</p>
<pre><code class="lang-php">increase(shadowsocks_data_bytes_per_location[<span class="hljs-number">1</span>d])
</code></pre>
<h3 id="heading-active-access-keys">Active Access Keys</h3>
<pre><code class="lang-php">sum(max(max_over_time(shadowsocks_data_bytes{access_key!=<span class="hljs-string">""</span>} [<span class="hljs-number">1</span>h])) by (access_key) &gt; <span class="hljs-keyword">bool</span> <span class="hljs-number">0</span>)
</code></pre>
<h3 id="heading-tcp-connections">TCP connections</h3>
<p>By access key, location and status</p>
<pre><code class="lang-php">increase(shadowsocks_tcp_connections_closed[<span class="hljs-number">1</span>d])
</code></pre>
<p>By location</p>
<pre><code class="lang-php">increase(shadowsocks_tcp_connections_opened[<span class="hljs-number">1</span>d])
</code></pre>
<h3 id="heading-udp">UDP</h3>
<p>Packets by location and status:</p>
<pre><code class="lang-php">increase(shadowsocks_udp_packets_from_client_per_location[<span class="hljs-number">1</span>d])
</code></pre>
<p>Associations (no breakdown):</p>
<pre><code class="lang-php">increase(shadowsocks_udp_nat_entries_added[<span class="hljs-number">1</span>d])
</code></pre>
<h2 id="heading-performance">Performance</h2>
<p>CPU usage by process:</p>
<pre><code class="lang-php">rate(process_cpu_seconds_total[<span class="hljs-number">10</span>m])
</code></pre>
<p>Memory by process:</p>
<pre><code class="lang-php">process_virtual_memory_bytes
</code></pre>
<h1 id="heading-reference">Reference</h1>
<p>The full list of metrics provided by <code>outline-ss-server</code> can be found in <a target="_blank" href="https://github.com/Jigsaw-Code/outline-ss-server/blob/master/cmd/outline-ss-server/metrics.go">its source code</a> from line 61.</p>
<h2 id="heading-as-curl-get-request">As curl GET request</h2>
<p>If you want, you also can get the same data with CURL (GET request), for example, to get data usage (in bytes) by specific access key (1) for the last day:</p>
<p>curl -g 'http://127.0.0.1:9090/api/v1/query?query=sum(increase(shadowsocks_data_bytes{access_key="1"}[1d]))by(access_key)'</p>
]]></content:encoded></item><item><title><![CDATA[Outline VPN + Telegram: bot  hosted on DigitalOcean Functions (serverless)]]></title><description><![CDATA[TLDR: if you want to try my free VPN bot, click this link @hidemail_vpn_bot
I decided to share what I have for my own Outline VPN Server - it simple bot where you can generate a new personal key to access this VPN server.
In the end, you will have Te...]]></description><link>https://blog.daneke.ge/outline-vpn-telegram-bot-hosted-on-digitalocean-functions-serverless</link><guid isPermaLink="true">https://blog.daneke.ge/outline-vpn-telegram-bot-hosted-on-digitalocean-functions-serverless</guid><category><![CDATA[telegram bot]]></category><category><![CDATA[outlinevpn]]></category><category><![CDATA[PHP]]></category><category><![CDATA[DigitalOcean]]></category><category><![CDATA[telegram]]></category><dc:creator><![CDATA[George Daneke]]></dc:creator><pubDate>Tue, 08 Aug 2023 16:39:00 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1692204182665/485480fe-6525-4945-896b-87291641a95d.webp" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>TLDR: if you want to try my free VPN bot, <a target="_blank" href="https://t.me/hidemail_vpn_bot">click this link @hidemail_vpn_bot</a></p>
<p>I decided to share what I have for my own Outline VPN Server - it simple bot where you can generate a new personal key to access this VPN server.</p>
<p>In the end, you will have Telegram chat id and @nickname of a user (if exist) inside a list of your outline VPN keys, like on cover for this post</p>
<p>Here is all code with a few comments, in general, you only need to create a telegram bot and put a token there, your chat id and outline server URL and Port.</p>
<pre><code class="lang-php"><span class="hljs-meta">&lt;?php</span>

<span class="hljs-keyword">const</span> TELEGRAM_BOT_TOKEN = <span class="hljs-string">'XXXXX:XXXXX'</span>; <span class="hljs-comment">// you can create new bot and generate this token with @BotFather bot - write there /newbot command</span>
<span class="hljs-keyword">const</span> TELEGRAM_BOT_ADMIN_CHAT_ID = <span class="hljs-string">'XXXXX'</span>; <span class="hljs-comment">// your chat id, you can find it with @cid_bot bot</span>

<span class="hljs-keyword">const</span> API_PORT = <span class="hljs-string">'PORT'</span>;
<span class="hljs-keyword">const</span> API_URL = <span class="hljs-string">'https://XXXXX:PORT/SOMEKEYFROMOUTLINE/'</span>;

<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">sendToTelegram</span>(<span class="hljs-params"><span class="hljs-keyword">array</span> $args, $url</span>): <span class="hljs-title">void</span>
</span>{

    $curl = curl_init();

    $urlWithName = $url . urlencode(<span class="hljs-string">'Name of your server for Outline VPN Client'</span>);

    $id = $args[<span class="hljs-string">'message'</span>][<span class="hljs-string">'chat'</span>][<span class="hljs-string">'id'</span>];
    $lang = $args[<span class="hljs-string">'message'</span>][<span class="hljs-string">'from'</span>][<span class="hljs-string">'language_code'</span>] ?? <span class="hljs-string">'en'</span>;

    <span class="hljs-comment">//if ($lang === 'en') {</span>
    $message = <span class="hljs-string">'Hello! I invite you to connect to my VPN (Outline) serverm so you will get access to the free Internet, wherever you are. Follow the instructions on the link provided in the invitation to download the app and set up your connection.

https://s3.amazonaws.com/outline-vpn/invite.html#'</span> . $url . <span class="hljs-string">' 

Have problems accessing the invitation link? Write to: @flatroy


Click and copy an access key: `'</span> . $urlWithName . <span class="hljs-string">'`
'</span>;
<span class="hljs-comment">//    } else {</span>
    <span class="hljs-comment">// with this IF you can add some message in different language if you want</span>
    <span class="hljs-comment">//  }</span>

    $message = urlencode($message);
    curl_setopt_array($curl, [
        CURLOPT_URL =&gt; <span class="hljs-string">'https://api.telegram.org/bot'</span>.TELEGRAM_BOT_TOKEN.<span class="hljs-string">'/sendMessage?chat_id='</span> . $id . <span class="hljs-string">'&amp;parse_mode=Markdown&amp;text='</span> . $message,
        CURLOPT_RETURNTRANSFER =&gt; <span class="hljs-literal">true</span>,
        CURLOPT_ENCODING =&gt; <span class="hljs-string">""</span>,
        CURLOPT_MAXREDIRS =&gt; <span class="hljs-number">10</span>,
        CURLOPT_TIMEOUT =&gt; <span class="hljs-number">30</span>,
        CURLOPT_HTTP_VERSION =&gt; CURL_HTTP_VERSION_1_1,
        CURLOPT_CUSTOMREQUEST =&gt; <span class="hljs-string">"GET"</span>,
        CURLOPT_POSTFIELDS =&gt; <span class="hljs-string">""</span>,
    ]);

    $response = curl_exec($curl);
    $err = curl_error($curl);

    curl_close($curl);

    <span class="hljs-comment">// send message to admin</span>
    $curl = curl_init();

    $id = $args[<span class="hljs-string">'message'</span>][<span class="hljs-string">'chat'</span>][<span class="hljs-string">'id'</span>];


    <span class="hljs-comment">// notify admin of bot</span>
    $message = <span class="hljs-string">'new user message: '</span> . $args[<span class="hljs-string">'message'</span>][<span class="hljs-string">'text'</span>] . <span class="hljs-string">" from @"</span> . $args[<span class="hljs-string">'message'</span>][<span class="hljs-string">'chat'</span>][<span class="hljs-string">'username'</span>] . <span class="hljs-string">' '</span> . $args[<span class="hljs-string">'message'</span>][<span class="hljs-string">'chat'</span>][<span class="hljs-string">'id'</span>] . <span class="hljs-string">' '</span> . $args[<span class="hljs-string">'message'</span>][<span class="hljs-string">'chat'</span>][<span class="hljs-string">'first_name'</span>] . <span class="hljs-string">' - lang: '</span> . $args[<span class="hljs-string">'message'</span>][<span class="hljs-string">'from'</span>][<span class="hljs-string">'language_code'</span>];

    curl_setopt_array($curl, [
        CURLOPT_URL =&gt; <span class="hljs-string">'https://api.telegram.org/bot'</span>.TELEGRAM_BOT_TOKEN.<span class="hljs-string">'/sendMessage?chat_id='</span>.TELEGRAM_BOT_ADMIN_CHAT_ID.<span class="hljs-string">'&amp;text='</span> . $message,
        CURLOPT_RETURNTRANSFER =&gt; <span class="hljs-literal">true</span>,
        CURLOPT_ENCODING =&gt; <span class="hljs-string">""</span>,
        CURLOPT_MAXREDIRS =&gt; <span class="hljs-number">10</span>,
        CURLOPT_TIMEOUT =&gt; <span class="hljs-number">30</span>,
        CURLOPT_HTTP_VERSION =&gt; CURL_HTTP_VERSION_1_1,
        CURLOPT_CUSTOMREQUEST =&gt; <span class="hljs-string">"GET"</span>,
        CURLOPT_POSTFIELDS =&gt; <span class="hljs-string">""</span>,
    ]);

    $response = curl_exec($curl);
    $err = curl_error($curl);

    curl_close($curl);
}


<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">main</span>(<span class="hljs-params"><span class="hljs-keyword">array</span> $args</span>): <span class="hljs-title">array</span>
</span>{
    $API_PORT = API_PORT;
    $API_URL = API_URL;


    <span class="hljs-keyword">if</span> ($args[<span class="hljs-string">'message'</span>][<span class="hljs-string">'text'</span>] === <span class="hljs-string">'/create'</span> || $args[<span class="hljs-string">'message'</span>][<span class="hljs-string">'text'</span>] === <span class="hljs-string">'/start'</span>) {

        <span class="hljs-comment">//check that if we already have key</span>
        $name = <span class="hljs-string">"@"</span> . $args[<span class="hljs-string">'message'</span>][<span class="hljs-string">'chat'</span>][<span class="hljs-string">'username'</span>] . <span class="hljs-string">' '</span> . $args[<span class="hljs-string">'message'</span>][<span class="hljs-string">'chat'</span>][<span class="hljs-string">'id'</span>] . <span class="hljs-string">' '</span> . $args[<span class="hljs-string">'message'</span>][<span class="hljs-string">'chat'</span>][<span class="hljs-string">'first_name'</span>] . <span class="hljs-string">' - from My Bot'</span>;

        $curl = curl_init();

        curl_setopt_array($curl, [
            CURLOPT_PORT =&gt; $API_PORT,
            CURLOPT_URL =&gt; $API_URL . <span class="hljs-string">'/access-keys/'</span>,
            CURLOPT_RETURNTRANSFER =&gt; <span class="hljs-literal">true</span>,
            CURLOPT_ENCODING =&gt; <span class="hljs-string">""</span>,
            CURLOPT_MAXREDIRS =&gt; <span class="hljs-number">10</span>,
            CURLOPT_TIMEOUT =&gt; <span class="hljs-number">30</span>,
            CURLOPT_HTTP_VERSION =&gt; CURL_HTTP_VERSION_1_1,
            CURLOPT_CUSTOMREQUEST =&gt; <span class="hljs-string">"GET"</span>,
            CURLOPT_POSTFIELDS =&gt; <span class="hljs-string">""</span>,
            CURLOPT_SSL_VERIFYHOST =&gt; <span class="hljs-literal">false</span>,
            CURLOPT_SSL_VERIFYPEER =&gt; <span class="hljs-literal">false</span>,
        ]);

        $response = curl_exec($curl);
        $err = curl_error($curl);
        curl_close($curl);

        <span class="hljs-keyword">if</span> ($err) {
            <span class="hljs-keyword">return</span> [<span class="hljs-string">"body"</span> =&gt; <span class="hljs-string">"cURL Error #:"</span> . $err];
        } <span class="hljs-keyword">else</span> {

            $keys = json_decode($response, <span class="hljs-literal">true</span>);
            <span class="hljs-keyword">foreach</span> ($keys[<span class="hljs-string">'accessKeys'</span>] <span class="hljs-keyword">as</span> $key) {

                <span class="hljs-keyword">if</span> ($key[<span class="hljs-string">'name'</span>] === $name) {
                    <span class="hljs-comment">//return ["body" =&gt; 'ok exists'];</span>

                    sendToTelegram($args, $key[<span class="hljs-string">'accessUrl'</span>]);
                    <span class="hljs-keyword">return</span> [<span class="hljs-string">"body"</span> =&gt; <span class="hljs-string">'ok'</span>];
                }
            }
        }

        $curl = curl_init();

        curl_setopt_array($curl, [
            CURLOPT_PORT =&gt; $API_PORT,
            CURLOPT_URL =&gt; $API_URL . <span class="hljs-string">'/access-keys/'</span>,
            CURLOPT_RETURNTRANSFER =&gt; <span class="hljs-literal">true</span>,
            CURLOPT_ENCODING =&gt; <span class="hljs-string">""</span>,
            CURLOPT_MAXREDIRS =&gt; <span class="hljs-number">10</span>,
            CURLOPT_TIMEOUT =&gt; <span class="hljs-number">30</span>,
            CURLOPT_HTTP_VERSION =&gt; CURL_HTTP_VERSION_1_1,
            CURLOPT_CUSTOMREQUEST =&gt; <span class="hljs-string">"POST"</span>,
            CURLOPT_POSTFIELDS =&gt; <span class="hljs-string">""</span>,
            CURLOPT_SSL_VERIFYHOST =&gt; <span class="hljs-literal">false</span>,
            CURLOPT_SSL_VERIFYPEER =&gt; <span class="hljs-literal">false</span>,
        ]);

        $response = curl_exec($curl);
        $err = curl_error($curl);
        curl_close($curl);

        <span class="hljs-keyword">if</span> ($err) {
            <span class="hljs-keyword">return</span> [<span class="hljs-string">"body"</span> =&gt; <span class="hljs-string">"cURL Error #:"</span> . $err];

        }

        <span class="hljs-keyword">echo</span> $response;
        $data = json_decode($response, <span class="hljs-literal">true</span>);
        sendToTelegram($args, $data[<span class="hljs-string">'accessUrl'</span>]);

        $curl = curl_init();

        curl_setopt_array($curl, [
            CURLOPT_PORT =&gt; $API_PORT,
            CURLOPT_URL =&gt; $API_URL . <span class="hljs-string">'/access-keys/'</span> . $data[<span class="hljs-string">'id'</span>] . <span class="hljs-string">'/name'</span>,
            CURLOPT_CUSTOMREQUEST =&gt; <span class="hljs-string">"PUT"</span>,
            CURLOPT_POSTFIELDS =&gt; <span class="hljs-string">"name="</span> . $name,
            CURLOPT_HTTPHEADER =&gt; [
                <span class="hljs-string">"Content-Type: application/x-www-form-urlencoded"</span>
            ],
            CURLOPT_RETURNTRANSFER =&gt; <span class="hljs-literal">true</span>,
            CURLOPT_ENCODING =&gt; <span class="hljs-string">""</span>,
            CURLOPT_MAXREDIRS =&gt; <span class="hljs-number">30</span>,
            CURLOPT_TIMEOUT =&gt; <span class="hljs-number">30</span>,
            CURLOPT_HTTP_VERSION =&gt; CURL_HTTP_VERSION_1_1,
            CURLOPT_SSL_VERIFYHOST =&gt; <span class="hljs-literal">false</span>,
            CURLOPT_SSL_VERIFYPEER =&gt; <span class="hljs-literal">false</span>,
        ]);

        $response = curl_exec($curl);
        $err = curl_error($curl);
        curl_close($curl);


        <span class="hljs-comment">// limit traffic</span>

        $curl = curl_init();

        curl_setopt_array($curl, [
            CURLOPT_PORT =&gt; $API_PORT,
            CURLOPT_URL =&gt; $API_URL . <span class="hljs-string">'/access-keys/'</span> . $data[<span class="hljs-string">'id'</span>] . <span class="hljs-string">'/data-limit'</span>,
            CURLOPT_RETURNTRANSFER =&gt; <span class="hljs-literal">true</span>,
            CURLOPT_ENCODING =&gt; <span class="hljs-string">""</span>,
            CURLOPT_MAXREDIRS =&gt; <span class="hljs-number">10</span>,
            CURLOPT_TIMEOUT =&gt; <span class="hljs-number">30</span>,
            CURLOPT_HTTP_VERSION =&gt; CURL_HTTP_VERSION_1_1,
            CURLOPT_CUSTOMREQUEST =&gt; <span class="hljs-string">"PUT"</span>,
            CURLOPT_POSTFIELDS =&gt; <span class="hljs-string">"{\"limit\":{\n\t\"bytes\": 200000000\n}}"</span>,
            CURLOPT_HTTPHEADER =&gt; [
                <span class="hljs-string">"Content-Type: application/json"</span>
            ],
        ]);

        $response = curl_exec($curl);
        $err = curl_error($curl);

        curl_close($curl);

        <span class="hljs-keyword">if</span> ($err) {
            <span class="hljs-keyword">echo</span> <span class="hljs-string">"cURL Error #:"</span> . $err;
        } <span class="hljs-keyword">else</span> {
            <span class="hljs-keyword">echo</span> $response;
        }

    }
    <span class="hljs-keyword">return</span> [<span class="hljs-string">"body"</span> =&gt; <span class="hljs-string">'ok'</span>];
}
</code></pre>
<p>This code is done only to use on <a target="_blank" href="https://m.do.co/c/34c0c54b7427">DigitalOcean</a> (serverless) functions: you can read about it here - <a target="_blank" href="https://www.digitalocean.com/products/functions">https://www.digitalocean.com/products/functions</a></p>
<p>Hope it will help anyone, cheers!</p>
<p><a target="_blank" href="https://www.digitalocean.com/?refcode=34c0c54b7427&amp;utm_campaign=Referral_Invite&amp;utm_medium=Referral_Program&amp;utm_source=badge"><img src="https://web-platforms.sfo2.cdn.digitaloceanspaces.com/WWW/Badge%201.svg" alt="DigitalOcean Referral Badge" /></a></p>
]]></content:encoded></item><item><title><![CDATA[Magento 2 - How to upload image to REST API (via POST request)]]></title><description><![CDATA[If you want to upload a product image using Rest API you need to pass the below parameters in your request:
post to https://{YOUDOMAIN}/rest/V1/products/{SKU}/media with body, JSON:
{
    "entry": {
        "media_type": "image",
        "label": nul...]]></description><link>https://blog.daneke.ge/magento-2-how-to-upload-image-to-rest-api-via-post-request</link><guid isPermaLink="true">https://blog.daneke.ge/magento-2-how-to-upload-image-to-rest-api-via-post-request</guid><category><![CDATA[magento 2]]></category><dc:creator><![CDATA[George Daneke]]></dc:creator><pubDate>Mon, 07 Aug 2023 11:52:57 GMT</pubDate><content:encoded><![CDATA[<p>If you want to upload a product image using Rest API you need to pass the below parameters in your request:</p>
<p>post to https://{YOUDOMAIN}/rest/V1/products/{SKU}/media with body, JSON:</p>
<pre><code class="lang-json">{
    <span class="hljs-attr">"entry"</span>: {
        <span class="hljs-attr">"media_type"</span>: <span class="hljs-string">"image"</span>,
        <span class="hljs-attr">"label"</span>: <span class="hljs-literal">null</span>,
        <span class="hljs-attr">"position"</span>: <span class="hljs-number">5</span>,
        <span class="hljs-attr">"disabled"</span>: <span class="hljs-literal">false</span>,
        <span class="hljs-attr">"types"</span>: [
            <span class="hljs-string">"image"</span>,
            <span class="hljs-string">"small_image"</span>,
            <span class="hljs-string">"thumbnail"</span>
        ],
           <span class="hljs-attr">"file"</span>: <span class="hljs-string">"test.jpg"</span>,
        <span class="hljs-attr">"content"</span>: {
          <span class="hljs-attr">"base64_encoded_data"</span>: <span class="hljs-string">"{BASE64_IMAGE}"</span>,
          <span class="hljs-attr">"type"</span>: <span class="hljs-string">"image/jpeg"</span>,
          <span class="hljs-attr">"name"</span>: <span class="hljs-string">"test.jpg"</span>
        }
    }
}
</code></pre>
<p>And if you want, before sending an image, you can encode it to base64 like this:</p>
<pre><code class="lang-php"><span class="hljs-meta">&lt;?php</span>
$path = <span class="hljs-string">'path/to/image.png'</span>;
$type = pathinfo($path, PATHINFO_EXTENSION);
$data = file_get_contents($path);
$base64 = <span class="hljs-string">'data:image/'</span> . $type . <span class="hljs-string">';base64,'</span> . base64_encode($data);
</code></pre>
<p>Note: you need to have a header "Authorization" with "Bearer {Magento 2 TOKEN}". How to get it? Just send POST request with your email and password to <a target="_blank" href="https://terminalx.localhost/rest/V1/integration/admin/token?username=George&amp;password=George123">https://{YOURDOMAIN}/rest/V1/integration/admin/token?username={ADMIN_NAME}&amp;password=</a>{ADMIN_PASSWORD} or generate a token via Magento 2 admin panel.</p>
]]></content:encoded></item></channel></rss>