Tuesday, August 16, 2022

PMM2 Apache2 Reverse Proxy Linux

Leave a Comment

Problem

You want to add a custom domain name for your PMM2 dashboard.

Solution

Use Apache2 Reverse Proxy to manage the domain name and also be able to generate Let's Encrypt certificates if needed.

Create the file /etc/apache2/sites-available/pmm.yourdomain.com
<VirtualHost *:80> 
  ProxyPreserveHost On
  ProxyRequests Off
  ServerName pmm.yourdomain.com
  ServerAlias www.pmm.yourdomain.com
  ProxyPass / http://localhost:880/
  ProxyPassReverse / http://localhost:880/
</VirtualHost>

<VirtualHost *:443>
  ProxyPreserveHost On
  ProxyRequests Off
  ServerName pmm.yourdomain.com
  ServerAlias pmm.yourdomain.com
  ProxyPass / http://localhost:8443/
  ProxyPassReverse / http://localhost:8443/
</VirtualHost>
Enable the domain by running
a2ensite pmm.yourdomain.com
service apache2 restart

Tips

  • Make sure to add the trailing slash / in the ProxyPass URL
Read More...

Thursday, January 27, 2022

Percona Monitoring and Management (PMM) update server address

Leave a Comment

Problem

Your PMM server address has changed (IP, hostname or port). The pmm-agent running on the monitored servers can't connect anymore. This guide assumes that you are on a Linux server (Ubuntu).
Read More...

Friday, October 22, 2021

MySQL/MariaDB can not grant privileges root@localhost

Leave a Comment

Problem

You can not grant MySQL table access to any users, getting the error: "access denied grant *.* root localhost".
The suggested fixes should fix any of those problems

  • mariadb can not grant access denied for user 'root'@'localhost'
  • MySQL grant access dennied root%localhost
  • create remote mysql users, can not grant access
  • grant identified via mysql_native_password
 

Solution

First, make sure the MySQL users table looks ok:
SELECT host,user,plugin,password,Grant_priv,Super_priv FROM mysql.user
Grant_priv - should be 'Y'
Super_priv - should be 'Y
plugin - should be 'mysql_native_password'

Fixing Grant_priv and Super_priv

UPDATE mysql.user SET Grant_priv='Y', Super_priv='Y' WHERE User='root';
FLUSH PRIVILEGES;
exit;
service mysql restart;

Update grants or reset root password

GRANT ALL PRIVILEGES ON *.* TO 'root'@'localhost' IDENTIFIED BY '<password>';
GRANT ALL ON *.* TO 'root'@'localhost';
FLUSH PRIVILEGES;
exit;
service mysql restart;

Fixing plugin:

UPDATE user SET plugin='mysql_native_password' WHERE User='root';
Read More...

Thursday, March 5, 2020

Parcel building with relative asset paths when using react-router

Leave a Comment

Problem:

You want to create a production build that can be uploaded in any folder, so it will work whether you upload it to site.com or site.com/app.

You use react-router in your app, so you also have to make sure that when you refresh a page, let's say site.com/contact-us it will still load the index.html from the correct location. The solution for this is usually to have a .htaccess file to load index.html whenever we try to load a path that doesn't exist:
RewriteEngine on

# Don't rewrite files or directories
RewriteCond %{REQUEST_FILENAME} -f [OR]
RewriteCond %{REQUEST_FILENAME} -d
RewriteRule ^ - [L]

# Rewrite everything else to index.html to allow html5 state links
RewriteRule ^ index.html [L]

Solution:

Step 1: Build parcel with relative asset paths, using --public-url ./:
parcel build src/index.html --no-source-maps --public-url ./

Step 2: The above rewrite only fixes loading the index.html file from the correct location, we still have to make sure all the other assets are loaded relative to your .htaccess file path. To do that, we load any missing file to our target folder:
# If we try to load a missing resource file, load it from folder root
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_URI} ^.*\.(jpg|css|js|gif|png|ico|mp3)$ [NC]
RewriteRule .+?([^\/]*\.*)$ $1 [L]

Step 3: Unforunately so far I don't have a solution for setting a relative path for react-router, so you still have to manually set the public url:
export const browserHistory = createBrowserHistory({
    basename: '/app'
});
This makes sure that when you have a router link to /contact-us it will actually link to /app/contact-us.
The good part is this path will only be referenced once in your build code, so you can easily change it by replacing that string even after the build was done.

Final .htaccess:

Those are the rewrites that make sure your index.html and assets are loaded correctly, even when you move your built app into a different folder.
RewriteEngine on
# Don't rewrite files or directories
RewriteCond %{REQUEST_FILENAME} -f [OR]
RewriteCond %{REQUEST_FILENAME} -d
RewriteRule ^ - [L]

# If we try to load a missing resource file, load it from folder root
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_URI} ^.*\.(jpg|css|js|gif|png|ico|mp3)$ [NC]
RewriteRule .+?([^\/]*\.*)$ $1 [L]

# Rewrite everything else to index.html to allow html5 state links
RewriteRule ^ index.html [L]

I am still thinking of a solution for using a relative basename in react-router, so that way links will also be correct when placed in any subfolder or subdomain.
Let me know if you know a way to use a relative basename for browserHistory.

Later edit: A hacky solution for relative basename

I did manage to figure out a dynamic solution for having a relative basename. It's based on the idea that once our app loads, we could detect the base folder based on the current location.pathname.
I know all the possible start values for all my Routes, which in my case are /sites or /settings. Once we know this, we can safely say that anything that is before those strings in the URL is the base path of our app.

const possibleStartPaths = ['/sites', '/settings'];
// Select everything in the pathname that appears before those strings.
// For example /subfolder/myapp/sites returns /subfolder/myapp
const baseMatch = window.location.pathname.match(
    new RegExp(`(.+?)(?:${possibleStartPaths.map((x) => x.replace('/', '\\/')).join('|')})`)
);
const basename = baseMatch ? baseMatch [1] + '/' : window.location.pathname;
export const browserHistory = createBrowserHistory({ basename });
Read More...

Monday, March 2, 2020

Detect Locale Change in React i18next

2 comments
I was looking for a way to re-render Chart.js charts when the react-i18next locale was changed. Looking through their documentation at https://react.i18next.com/ I didn't see any hook that could be used to detect current locale.

Problem

When the translation language is changed I also change the moment.js locale for my time-series charts in Chart.js. I need a way to detect language changes so I can rerender the charts.

Solution

Add the locale ISO code into the translation files and use that.
What I did was:
  1. Add a new translation key in my translation files: 'current_locale': 'en' for the English translation, 'current_locale': 'ro' for Romanian.
  2. Use the useTranslation() hook:
    const { t } = useTranslation();
    
  3. Rerender the chart when language is changed:
    useEffect(() => {
       // This will be now called when the locale is changed
    }, [t('current_locale')])
    

Improvements

You can also create a custom hook if you want:
export const useLocale = () => {
    const { t } = useTranslation();
    return t('current_locale');
};
Now you can use the locale value directly:
const locale = useLocale();
useEffect(() => {
   // This will be now called when the locale is changed
}, [locale])

Read More...

Friday, February 28, 2020

Finally switched to HTTPS!

Leave a Comment
Switching this blog to HTTPS took a lot longer a was harder than expected due to some Blogger bugs. The Google rankings were hit hard because the blog was not served over HTTPS, this made me spend more time and look for a solution.


Blogger: Whoops, that's an error! (bX-2kvjq7)

I have tried switching this Blogger site to HTTPS multiple times, but it never worked because whenever I switched HTTPS Availability to Yes in the settings I got this error: Whoops, that's an error! (bX-2kvjq7).




The actual problem: domain validation

The solution in my case was to remove the custom domain name, add it again and complete the DNS  validation process using the CNAME and TXT entries.
To remove your domain name go to Settings -> Basic -> Publishing -> Edit and delete the domain name and save.


After that I could enable HTTPS Availability without any error.

While writing this post things broke again

While taking the above screenshots I disabled HTTPS availability, after turning it on again the blog was stuck in a permanent 301 redirect loop, leading to ERR_TOO_MANY_REDIRECTS.
I do use Cloudflare on top of my Blogger blog, but this happens probably because of some Blogger bug and compatibility with Cloudflare.

I was not able to fix this redirect loop while keeping HTTPS availability to Yes, but after switching it to No I just enforced the Always Use HTTPS rule in Cloudflare and now it seems to work.

This solution might also work for other error codes such as bX-aa1bde or bX-gtb2wc.


Read More...